私は既存の Java コードから C++ プロジェクトを開発しています。何百万もの整数で構成される同じテスト ファイルから読み取る次の C++ コードと Java コードがあります。
C++:
int * arr = new int[len]; //len is larger than the largest int from the data
fill_n(arr, len, -1); //fill with -1
long loadFromIndex = 0;
struct stat sizeResults;
long size;
if (stat(fileSrc, &sizeResults) == 0) {
size = sizeResults.st_size; //here size would be ~551950000 for 552M test file
}
mmapFile = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, pageNum*pageSize);
long offset = loadFromIndex % pageSize;
while (offset < size) {
int i = htonl(*((int *)(mmapFile + offset)));
offset += sizeof(int);
int j = htonl(*((int *)(mmapFile + offset)));
offset += sizeof(int);
swapElem(i, j, arr);
}
return arr;
ジャワ:
IntBuffer bb = srcFile.getChannel()
.map(MapMode.READ_ONLY, loadFromIndex, size)
.asIntBuffer().asReadOnlyBuffer();
while (bb.hasRemaining()) {
int i = bb.get();
int j = bb.get();
swapElem(i, j, arr); //arr is an int[] of the same size as the arr in C++ version, filled with -1
}
return arr;
void swapElem(arr)
C++ と Java では同じです。配列内の値を比較して変更しますが、元のコードをここに投稿するには長いです。テスト目的で、ループがデッドコードにならないように、次の関数に置き換えました。
void swapElem(int i, int j, int * arr){ // int[] in Java
arr[i] = j;
}
私は、C++ バージョンが Java バージョンよりも優れているはずだと思っていましたが、テストの結果は逆で、Java コードは C++ コードよりもほぼ 2 倍高速です。C++ コードを改善する方法はありますか?
C ++ のmmapFile+offset
は何度も繰り返されるので、それは O(n) 個の追加であり、 は O(n) 個の追加ですoffset+=sizeof(int)
。ここで、n は読み取る整数の数です。Java のIntBuffer.get()
場合、バッファのインデックスから直接読み取るだけなので、バッファ インデックスを 1 ずつインクリメントする O(n) 回を除いて加算操作は必要ありません。したがって、バッファ インデックスのインクリメントを含めて、C++ は O(2n) 回の加算を行いますが、Java は O を取得します。 (n) 追加。何百万ものデータになると、パフォーマンスに大きな違いが生じる可能性があります。
この考えに従って、C++ コードを次のように変更しました。
mmapBin = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, pageNum*pageSize);
int len = size - loadFromIndex % pageSize;
char * offset = loadFromIndex % pageSize + mmapBin;
int index = 0;
while (index < len) {
int i = htonl(*((int *)(offset)));
offset += sizeof(int);
int j = htonl(*((int *)(offset)));
offset += sizeof(int);
index+=2*sizeof(int);
}
わずかなパフォーマンスの向上があると想定していましたが、そうではありません。
C++ コードの動作が Java コードよりも遅い理由を誰か説明できますか? ありがとう。
アップデート:
-O2 が機能しないと言ったとき、私の側に問題があったことをお詫びしなければなりません。Makefile を台無しにして、C++ コードが -O2 を使用して再コンパイルされないようにしました。パフォーマンスを更新したところ、-O2 を使用した C++ バージョンが Java バージョンよりもパフォーマンスが向上しました。これで問題は解決しますが、誰かが C++ コードを改善する方法を共有したい場合は、フォローします。一般的には、Java コードよりも 2 倍高速になると予想されますが、現在はそうではありません。ご意見をお寄せいただきありがとうございます。
コンパイラ: g++
フラグ: -Wall -c -O2
Java バージョン: 1.8.0_05
ファイルのサイズ: 552MB、すべて 4 バイト整数
プロセッサー: 2.53 GHz Intel Core 2 Duo
メモリ 4GB 1067 MHz DDR3
更新されたベンチマーク:
バージョン時間(ミリ秒)
C++: ~1100
ジャワ: ~1400
C++ (while ループなし): ~35
Java (while ループなし): ~40
これらのコードの前に、〜 35 ミリ秒のパフォーマンスを引き起こすものがあります (ほとんどの場合、配列は -1 で埋められます) が、ここでは重要ではありません。