我使用 SIMD 加载指令从内存加载元素,假设使用 Altivec,假设地址对齐:
float X[SIZE];
vector float V0;
unsigned FLOAT_VEC_SIZE = sizeof(vector float);
for (int load_index =0; load_index < SIZE; load_index+=FLOAT_VEC_SIZE)
{
V0 = vec_ld(load_index, X);
/* some computation involving V0*/
}
现在,如果 SIZE 不是 FLOAT_VEC_SIZE 的倍数,则 V0 可能在上次循环迭代中包含一些无效的内存元素。避免这种情况的一种方法是减少一次迭代循环,另一种方法是屏蔽潜在的无效元素,这里还有其他有用的技巧吗?考虑到上述内容是一组嵌套循环的最内部。因此任何额外的非 SIMD 指令都会带来性能损失!
最佳答案
理想情况下,您应该将数组填充为 vec_step(vector float)
的倍数(即 4 个元素的倍数),然后从 SIMD 处理中屏蔽掉任何其他不需要的值或使用标量代码来处理最后几个元素,例如
const INT VF_ELEMS = vec_step(vector float);
const int VEC_SIZE = (SIZE + VF_ELEMS - 1) / VF_ELEMS; // number of vectors in X, rounded up
vector float VX[VEC_SIZE]; // padded array with 16 byte alignment
float *X = = (float *)VX; // float * pointer to base of array
for (int i = 0; i <= SIZE - VF_ELEMS; i += VF_ELEMS)
{ // for each full SIMD vector
V0 = vec_ld(0, &X[i]);
/* some computation involving V0 */
}
if (i < SIZE) // if we have a partial vector at the end
{
#if 1 // either use SIMD and mask out the unwanted values
V0 = vec_ld(0, &X[i]);
/* some SIMD computation involving partial V0 */
#else // or use a scalar loop for the remaining 1..3 elements
/* small scalar loop to handle remaining points */
#endif
}
关于simd - 使用 SIMD 指令避免无效内存加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13029427/