我使用SIMD来计算快速的求幂结果。我将时序与非simd代码进行比较。幂运算采用平方和乘法算法。
普通(非simd)版本的代码:
b = 1;
for (i=WPE-1; i>=0; --i){
ew = e[i];
for(j=0; j<BPW; ++j){
b = (b * b) % p;
if (ew & 0x80000000U) b = (b * a) % p;
ew <<= 1;
}
} SIMD版本:
B.data[0] = B.data[1] = B.data[2] = B.data[3] = 1U;
P.data[0] = P.data[1] = P.data[2] = P.data[3] = p;
for (i=WPE-1; i>=0; --i) {
EW.data[0] = e1[i]; EW.data[1] = e2[i]; EW.data[2] = e3[i]; EW.data[3] = e4[i];
for (j=0; j<BPW;++j){
B.v *= B.v; B.v -= (B.v / P.v) * P.v;
EWV.v = _mm_srli_epi32(EW.v,31);
M.data[0] = (EWV.data[0]) ? a1 : 1U;
M.data[1] = (EWV.data[1]) ? a2 : 1U;
M.data[2] = (EWV.data[2]) ? a3 : 1U;
M.data[3] = (EWV.data[3]) ? a4 : 1U;
B.v *= M.v; B.v -= (B.v / P.v) * P.v;
EW.v = _mm_slli_epi32(EW.v,1);
}
} 问题是,尽管simd版本的计算是正确的,但它比非simd版本花费了更多的时间。
请帮我调试一下原因。任何关于SIMD编码的建议也是受欢迎的。
谢谢和问候,Anup。
发布于 2010-10-25 15:43:57
for循环中的所有函数都应该是SIMD函数,而不仅仅是两个。为你的两个函数设置参数所花费的时间比你的原始示例(很可能是由编译器优化的)要差。
发布于 2010-10-25 18:49:07
用于32位int数据的SIMD循环通常如下所示:
for (i = 0; i < N; i += 4)
{
// load input vector(s) with data at array index i..i+3
__m128 va = _mm_load_si128(&A[i]);
__m128 vb = _mm_load_si128(&B[i]);
// process vectors using SIMD instructions (i.e. no scalar code)
__m128 vc = _mm_add_epi32(va, vb);
// store result vector(s) at array index i..i+3
_mm_store_si128(&C[i], vc);
}如果你发现你需要在循环中的标量代码和SIMD代码之间移动,那么你可能不会从SIMD优化中得到任何东西。
SIMD编程的大部分技能来自于寻找方法,使您的算法与给定SIMD体系结构提供的有限数量的受支持指令和数据类型一起工作。您通常需要利用您的数据集的先验知识来获得最佳性能,例如,如果您确定您的32位整数值实际上具有适合16位的范围,那么这将使您的算法的乘法部分更容易实现。
https://stackoverflow.com/questions/4012551
复制相似问题