このような内部ループがあります
for(i=0 ;i<n;i++){
x[0] += A[i] * z[0];
x[1] += A[i] * z[1];
x[2] += A[i] * z[2];
x[3] += A[i] * z[3];
}
内側の 4 つの命令は、コンパイラによって SSE 命令に簡単に変換できます。現在のコンパイラはこれを行いますか? 彼らがそうする場合、コンパイラでこれを強制するために私は何をしなければなりませんか?
このような内部ループがあります
for(i=0 ;i<n;i++){
x[0] += A[i] * z[0];
x[1] += A[i] * z[1];
x[2] += A[i] * z[2];
x[3] += A[i] * z[3];
}
内側の 4 つの命令は、コンパイラによって SSE 命令に簡単に変換できます。現在のコンパイラはこれを行いますか? 彼らがそうする場合、コンパイラでこれを強制するために私は何をしなければなりませんか?
あなたが提供したものから、これはベクトル化できません。これは、ポインターが互いにエイリアスになる可能性があるためです。つまり、x
配列がA
orとオーバーラップする可能性がありz
ます。
x
コンパイラを支援する簡単な方法は、 as として宣言すること__restrict
です。別の方法は、次のように書き直すことです。
for(i=0 ;i<n;i++)
{
float Ai=A[i];
float z0=z[0], z1=z[1], z2=z[2], z3=z[3];
x[0] += Ai * z0;
x[1] += Ai * z1;
x[2] += Ai * z2;
x[3] += Ai * z3;
}
私は実際にコンパイラーにコードを自動ベクトル化させようとしたことがないので、それができるかどうかはわかりません。ベクトル化されなくても、ロードヒットストアを発生させることなく、ロードとストアをより効率的に順序付けできるため、高速になるはずです。
コンパイラよりも多くの情報がある場合 (たとえば、ポインターが 16 バイトでアラインされているかどうか)、それを有利に使用できるはずです (たとえば、アラインされたロードを使用する)。コンパイラよりも多くのことを知っている場合にのみ、常にコンパイラを打ち負かすようにすべきだと言っているわけではないことに注意してください。
参考文献: