私が書いているラスター化アルゴリズムのいくつかのエラー値をクランプするために使用している、最も内側のループに少しのコードがあります。
float cerror[4] = {
MINF(error[0], 1.0f),
MINF(error[1], 1.0f),
MINF(error[2], 1.0f),
MINF(error[3], 1.0f)
};
ここで、MINF は単に MINF(a,b) = ((a) < (b)) ? (a) : (b)
この内側のループで更新しなければならないエラー値が 4 つあることがわかりました。すべて float です。したがって、それらをすべて SSE レジスタに格納し、最小値を個別ではなく minps で計算できれば素晴らしいと思いますが、コンパイラは私のためにそれをしていないようです。
ベクトライザーの出力を確認できるように、独自の関数に移動してみました。
void fclamp4(float* __restrict__ aa, float* __restrict__ bb) {
for (size_t ii=0; ii < 4; ii++) {
aa[ii] = (bb[ii] > 1.0) ? 1.0f : bb[ii];
}
}
これは私に次のようなものを与えます:
inc/simplex.h:1508: 注: ベクトル化されていません: サポートされていないデータ型 bool
inc/simplex.h:1507: 注: 関数内でベクトル化された 0 ループ。
コンパイラが私のためにこれを行うように奨励する方法はありますか? コードの移植性を維持するために、回避できるのであれば、組み込み関数に直接スキップしたくありません。おそらく、一般的なパターンに関する一般的なリファレンスはありますか?
最後に、エラー/cerror/エラーのインクリメントはすべてスタック上の float[4] 配列に格納されています。これらを手動で調整する必要がありますか?それともコンパイラで処理できますか?
編集:整列されたタイプで遊んでいて、まだサイコロはありません。
#include <stdio.h>
#include <stdlib.h>
typedef float __attribute__((aligned (16))) float4[4];
inline void doit(const float4 a, const float4 b, float4 c) {
for (size_t ii=0; ii < 4; ii++) {
c[ii] = (a[ii] < b[ii]) ? a[ii] : b[ii];
}
}
int main() {
float4 a = {rand(), rand(), rand(), rand() };
float4 b = {1.0f, 1.0f, 1.0f, 1.0f };
float4 c;
doit((float*)&a, (float*)&b, (float*)&c);
printf("%f\n", c[0]);
}
ベクトライザーは次のように述べています。
ssetest.c:7: 注: vect_model_load_cost: 整列。
ssetest.c:7: 注: vect_model_load_cost: inside_cost = 4, outside_cost = 0 .
ssetest.c:7: 注: vect_model_load_cost: 整列。
ssetest.c:7: 注: vect_model_load_cost: inside_cost = 4, outside_cost = 0 .
ssetest.c:7: 注: ベクトル化されていません: 関連する stmt はサポートされていません: D.3177D.3177_22 = iftmp.4_18 < iftmp.4_21;ssetest.c:12: 注: 関数内のベクトル化された 0 ループ。
もう一度編集: GCC 4.4.7 (RHEL 6) と GCC 4.6 (Ubuntu) でこれを試してみましたが、どちらもうまくいきませんでした。