GCC的vector extensions提供了一個很好的,合理的便攜方式訪問不同硬件架構上的一些SIMD指令,而不訴諸於hardware specific intrinsics(或自動矢量化)。爲GCC的向量擴展加載數據
一個真實的用例,正在計算一個簡單的加法校驗和。不清楚的一件事是如何安全地將數據加載到矢量中。
typedef char v16qi __attribute__ ((vector_size(16)));
static uint8_t checksum(uint8_t *buf, size_t size)
{
assert(size%16 == 0);
uint8_t sum = 0;
vec16qi vec = {0};
for (size_t i=0; i<(size/16); i++)
{
// XXX: Yuck! Is there a better way?
vec += *((v16qi*) buf+i*16);
}
// Sum up the vector
sum = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5] + vec[6] + vec[7] + vec[8] + vec[9] + vec[10] + vec[11] + vec[12] + vec[13] + vec[14] + vec[15];
return sum;
}
鑄造的指針向量類型似乎工作,但我很擔心,如果SIMD硬件預計矢量類型正確對齊,這可能在一個可怕的方式爆炸。
我想到的唯一的其他選擇是使用臨時向量並顯式加載值(通過memcpy或元素明智的賦值),但是在測試中,這抵消了大部分加速獲得的SIMD指令的使用。理想情況下,我會想象這將是一個通用的__builtin_load()
函數,但似乎都不存在。
將數據加載到矢量中的更安全方式可能會導致對齊問題?
在GCC x86_64的上對齊的內存運行,這將導致SIGSEGV,當CPU嘗試將未對齊的內存加載到SSE寄存器時。 一個合理的選擇似乎只是校驗和對齊的內存,或者使用正常循環將字節總和,直到第一個16字節邊界。 – dcoles 2012-02-17 00:18:39
在您當前的代碼中,如果編譯器知道輸入(但總和不好),加載數據實際上編譯得很好:https://godbolt.org/g/DeR3Qv。沒有關於輸入的知識就不太好:https:// godbolt。組織/克/ LxEkhp – ZachB 2016-09-21 18:14:20