多くの場合、あまりにも多くの要因が関係しています...そして、両方の方法を示すのは簡単です。
たとえば、次のループを分割すると、ほぼ2倍の速度低下が発生します(下部に完全なテストコードがあります)。
for (int c = 0; c < size; c++){
data[c] *= 10;
data[c] += 7;
data[c] &= 15;
}
そして、これは、1回ではなく3回ループする必要があり、1回ではなくアレイ全体を3回パスする必要があるため、ほぼ明白です。
一方、この質問を見ると、要素ごとの追加が、結合されたループよりも個別のループではるかに高速であるのはなぜですか?
for(int j=0;j<n;j++){
a1[j] += b1[j];
c1[j] += d1[j];
}
メモリアライメントのために、逆のことが時々当てはまります。
これから何を取る?
ほとんど何でも起こり得ます。どちらの方法も常に高速であるとは限らず、ループ内の内容に大きく依存します。
そのため、このような最適化によってパフォーマンスが向上するかどうかを判断することは、通常、試行錯誤です。十分な経験があれば、かなり自信を持って(知識に基づいて)推測することができます。しかし、一般的に、何かを期待してください。
「追加のforループごとに、2つのint割り当てに相当するコストがかかります。」
あなたはそれがそれほど単純ではないということは正しいです。実際、それは非常に複雑なので、数字はあまり意味がありません。ループの反復は、あるコンテキストではXサイクルかかる場合がありますが、アウトオブオーダー実行やデータの依存関係などの多数の要因により、別のコンテキストではYサイクルかかります。
パフォーマンスはコンテキストに依存するだけでなく、プロセッサによっても異なります。
テストコードは次のとおりです。
#include <time.h>
#include <iostream>
using namespace std;
int main(){
int size = 10000;
int *data = new int[size];
clock_t start = clock();
for (int i = 0; i < 1000000; i++){
#ifdef TOGETHER
for (int c = 0; c < size; c++){
data[c] *= 10;
data[c] += 7;
data[c] &= 15;
}
#else
for (int c = 0; c < size; c++){
data[c] *= 10;
}
for (int c = 0; c < size; c++){
data[c] += 7;
}
for (int c = 0; c < size; c++){
data[c] &= 15;
}
#endif
}
clock_t end = clock();
cout << (double)(end - start) / CLOCKS_PER_SEC << endl;
system("pause");
}
出力(1ループ): 4.08秒
出力(3ループ): 7.17秒