以下是我尝试使用SSE加速的示例C代码,这两个数组长度为3072个元素,并且双精度浮点数,如果我不需要精度双精度浮点数,可以将其降低到浮点数。 $ b
double sum = 0.0; (k = 0; k <3072; k ++){ sum + = fabs(sima [k] - simb [k])的 ; } double fp =(1.0 - (sum /(255.0 * 1024.0 * 3.0)));无论如何,我目前的问题是如何在SSE寄存器中执行fabs步骤,以便双打或浮动我可以将整个计算保留在SSE寄存器中,以便它保持快速,并且可以通过部分展开此循环来并行化所有步骤。
这里是我的一些资源找到 fabs()asm 或可能翻转标志 - SO 但是第二个弱点需要一个有条件的检查。
解决方案可能最简单的方法如下:
__ m128d vsum = _mm_set1_pd(0.0); (k = 0; k <3072; k + = 2) { __m128d va = _mm_load_pd(& sima [k]); // init部分和; //从sima载入2个双打,simb __m128d vb = _mm_load_pd(& simb [k]); __m128d vdiff = _mm_sub_pd(va,vb); // calc diff = sima - simb __m128d vnegdiff = mm_sub_pd(_mm_set1_pd(0.0),vdiff); // calc neg diff = 0.0 - diff __m128d vabsdiff = _mm_max_pd(vdiff,vnegdiff); // calc abs diff = max(diff, - diff) vsum = _mm_add_pd(vsum,vabsdiff); //累积两个部分和 $ $ $ $ b $ p注意这可能不比标量快现代x86 CPU上的代码,无论如何它们通常都有两个FPU。但是,如果你可以下降到单精度,那么你可能会得到2倍的吞吐量改进。还要注意,你需要将 vsum 转换为循环后的标量值,但这样做相当微不足道,并且不是性能关键。
Here's the sample C code that I am trying to accelerate using SSE, the two arrays are 3072 element long with doubles, may drop it down to float if i don't need the precision of doubles.
double sum = 0.0; for(k = 0; k < 3072; k++) { sum += fabs(sima[k] - simb[k]); } double fp = (1.0 - (sum / (255.0 * 1024.0 * 3.0)));Anyway my current problem is how to do the fabs step in a SSE register for doubles or float so that I can keep the whole calculation in the SSE registers so that it remains fast and I can parallelize all of the steps by partly unrolling this loop.
Here's some resources I've found fabs() asm or possibly this flipping the sign - SO however the weakness of the second one would need a conditional check.
解决方案Probably the easiest way is as follows:
__m128d vsum = _mm_set1_pd(0.0); // init partial sums for (k = 0; k < 3072; k += 2) { __m128d va = _mm_load_pd(&sima[k]); // load 2 doubles from sima, simb __m128d vb = _mm_load_pd(&simb[k]); __m128d vdiff = _mm_sub_pd(va, vb); // calc diff = sima - simb __m128d vnegdiff = mm_sub_pd(_mm_set1_pd(0.0), vdiff); // calc neg diff = 0.0 - diff __m128d vabsdiff = _mm_max_pd(vdiff, vnegdiff); // calc abs diff = max(diff, - diff) vsum = _mm_add_pd(vsum, vabsdiff); // accumulate two partial sums }Note that this may not be any faster than scalar code on modern x86 CPUs, which typically have two FPUs anyway. However if you can drop down to single precision then you may well get a 2x throughput improvement.
Note also that you will need to combine the two partial sums in vsum into a scalar value after the loop, but this is fairly trivial to do and is not performance-critical.
更多推荐
如何使用SSE指令集来完成2个双精度浮点数或4个浮点数? (至SSE4)
发布评论