我試圖使用Intel Intrinsics在float
陣列上快速執行操作。這些行動本身似乎運作良好;但是,當我嘗試將操作的結果轉換爲標準C變量時,我得到一個SEGFAULT。如果我將下面的指示線註釋掉,程序就會運行。如果我保存指定行的結果,但不以任何方式操縱它,程序運行正常。只有當我試圖(以任何方式)與_mm_cvtss_f32(C)
的結果進行交互時,我的程序纔會崩潰。有任何想法嗎?使用生成的浮點數時出現SSE SIMD分段錯誤
float proc(float *a, float *b, int n, int c, int width) {
// Operation: SUM: (A - B)^2
__m128 A, B, C;
float total = 0;
for (int d = 0, k = 0; k < c; d += width, k++) {
for (int i = 0; i < n/4 * 4; i += 4) {
A = _mm_load_ps(&a[i + d]);
B = _mm_load_ps(&b[i + d]);
C = _mm_sub_ps(A, B);
C = _mm_mul_ps(C, C);
C = _mm_hadd_ps(C, C);
C = _mm_hadd_ps(C, C);
total += _mm_cvtss_f32(C); // SEGFAULT HERE
}
for (int i = n/4 * 4; i < n; i++) {
int diff = a[i + d] - b[i + d];
total += diff * diff;
}
}
return total;
}
你確定你的程序實際上是在你引用的指令上崩潰的,或者是編譯器只是優化了剩餘的循環,如果你刪除'_mm_cvtss_f32()'行(它沒有任何其他可見的副作用) ?由於使用對齊的加載指令,因此潛在的故障原因可能是「a」和「b」陣列的不正確對齊。你確定它們是16字節對齊的嗎?在當代英特爾硬件上,16字節對齊和不對齊負載之間的性能差別非常小(「movaps」的指令編碼比「movups」短,但就是這一點)。 –
謝謝你,我把'load'改成了'loadu',它現在好像工作了! – Simon
@JasonR:它們的編碼長度相同。 http://www.felixcloutier.com/x86/MOVAPS.html與http://www.felixcloutier.com/x86/MOVUPS.html。如果您比較反彙編,其中一個是否有REX前綴或不同的尋址模式?無論如何,當數據在運行時對齊時,它們的表現完全相同,但當L1高速緩存讀取帶寬是瓶頸時,對齊的負載具有優勢。確保您的數據在價格低廉時保持一致是個不錯的主意。 –