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