4

C と Java で Eratosthene のふるいアルゴリズムを開発しましたが、いくつかの問題に遭遇しました。

素数の配列を管理するために、C では char の配列 (要素ごとに 8 ビット) を使用し、Java では boolean の配列 (要素ごとに 8 ビット) を使用しました。

N=1,000,000,000 まで素数を計算しようとすると (N 要素の配列があるため)、Java アプリケーションはうまく機能します (ヒープ サイズを 1.5GB に拡張しました)。C アプリケーションで同じことをしようとすると、メモリが不足します (制限は N=680,000,000 です)。

同じ N=500,000,000 で両方のアプリケーションを実行すると、確認したところ、両方とも約 512MB の RAM を占有しているため、Java アプリケーションが N=1,000,000,000 で正常に動作する場合、C アプリケーションがすぐに実行に失敗する理由がわかりません。

私が知らないJavaの「-Xmx1536m」のようなCの「オプション」はありますか?

4GB の RAM があり、Windows 7 64 ビットを使用しています。sizeof(size_t) の値も確認したところ 32 だったので、4GB のメモリを適切に割り当てることができると思います。

編集: Cygwin の 64 ビット版を試してみたところ、N=1,000,000,000 で正常に動作するようになりました。これには理由がありますか?1GBのメモリには64ビットではなく32ビットが「必要」だと思います...

ここにアプリケーションのソースがあります。

ジャワ:

int N = 1000000000;
int m;

boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
    isPrime[i] = true;
}

for (int i = 2; i*i <= N; i++) {
    if (isPrime[i]) {
        for (int j = i; (m = i*j) <= N; j++) {
            isPrime[m] = false;
        }
    }
}

子:

int N = 1000000000;
int i, j, m;
char *isPrime;
isPrime = malloc(sizeof(char)*(N+1));

for (i = 2; i <= N; i++) {
    isPrime[i] = 1;
}

for (i = 2; i*i <= N; i++) {
    if (isPrime[i]) {
        for (j = i; (m = i*j) <= N; j++) {
            isPrime[m] = 0;
        }
    }
}
4

1 に答える 1

1

これは、C ランタイムと JVM の間でメモリ割り当てが異なることが原因である可能性があります。C ランタイムは、配列のメモリの連続ブロックを保証し、配列要素にアクセスするためのポインター演算を実行できるようにします。Java には、より大きな配列を割り当てることを可能にするような保証はありません。

于 2013-10-17T21:37:35.077 に答える