我正在尝试学习使用SSE,我正在编写的程序之一要求使用模数除法,因此我为此编写了代码(很抱歉,它被过分评价):
__m128i SSEModDiv(__m128i input, __m128i divisors)
{
//Error Checking (div by zero)
/*__m128i zeros = _mm_set1_epi32(0);
__m128i error = _mm_set1_epi32(-1);
__m128i zerocheck = _mm_cmpeq_epi32(zeros, divisors);
if (_mm_extract_epi16(zerocheck, 0) != 0)
return error;
if (_mm_extract_epi16(zerocheck, 2) != 0)
return error;
if (_mm_extract_epi16(zerocheck, 4) != 0)
return error;
if (_mm_extract_epi16(zerocheck, 6) != 0)
return error;*/
//Now for the real work
__m128 inputf = _mm_cvtepi32_ps(input);
__m128 divisorsf = _mm_cvtepi32_ps(divisors);
/*__m128 recip = _mm_rcp_ps(divisorsf); //Takes reciprocal
__m128 divided = _mm_mul_ps(inputf, recip); //multiplies by reciprical values*/
__m128 divided = _mm_div_ps(inputf, divisorsf);
__m128i intermediateint = _mm_cvttps_epi32(divided); //makes an integer version truncated
__m128 intermediate = _mm_cvtepi32_ps(intermediateint);
__m128 multiplied = _mm_mul_ps(intermediate, divisorsf); //multiplies the intermediate with the divisors
__m128 mods = _mm_sub_ps(inputf, multiplied); //subtracts to get moduli
return _mm_cvtps_epi32(mods);
}
问题在于,这大约与分别释放四个32位整数的每个元素的模数一样快,而调试(通过性能分析发现)则要慢大约10倍。
谁能给我任何有关如何使此功能更快的指针?
-我无法使用SVML,因为我正在使用Visual Studio-
对于一般的价值input
和divisors
存在整数除法或模量没有有用的SIMD x86指令,因此最好使用标量整数除法。但是,在某些特殊情况下,SIMD整数模量可以更快地完成。
例如,如果您要执行(a + b)%c并且a和b已被减少(即a<c
and b<c
),则可以使用比较和减法,如下所示:
z = a + b
if(z>=c) z-=c;
我在此示例中进行了此操作vectorizing-modular-arithmetic
另一个例子是,除数不是编译时间常数,而是在循环内仍然是常数,那么您可以使用浮点除法的类似思想。浮点除法的一个常见技巧是预先计算除数的倒数并像这样进行乘法:
float fact = 1.0/x;
for(int i=0; i<n; i++) {
z[i] = fact*y[i]; //z[i] = y[i]/x;
}
您可以对整数除法使用类似的技术,该技术将整数除法转换为带移位的整数乘法。
y / x ≈ y * (2 n / x) >> n
有几种不同的技术可以确定因子(又称幻数)(2 n / x)
和移位n
。实际上,大多数编译器已经为编译时间常数和除法了。例如x/7
,如果您尝试查看GCC或MSVC的程序集输出,您会发现它们实际上并没有进行整数除法,而是使用与从http:// www计算的相同的幻数和移位进行乘法和移位。 hackersdelight.org/magic.htm。
我在运行时使用Agner Fog的Vector Class Library或他的Subroutine库进行此操作。这两个库都将在运行时为SSE和AVX整数除法计算魔术数并为您移位。
但是正如我在回答开头所说的,如果你想做
for(int i=0; i<n; i++) {
z[i] = y[i]%x[i];
}
并且x[i]
不是循环中的常数,最好坚持标量除法/模量。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句