我将不得不编写一个非常基本的校验和函数,例如:
char sum(const char * data, const int len)
{
char sum(0);
for (const char * end=data+len ; data<end ; ++data)
sum += *data;
return sum;
}
那是微不足道的。现在,我该如何优化呢? 首先,我应该使用一些std :: for_each与lambda或类似的东西:
char sum2(const char * data, const int len)
{
char sum(0);
std::for_each(data, data+len, [&sum](char b){sum+=b;});
return sum;
}
接下来,我可以使用多个线程/核心来总结块,然后添加结果。我不会把它写下来,我担心创建线程的成本(或者从池中获取它们),然后切断阵列,然后调度所有内容等等,考虑到我大部分时间都不会很好计算小数组的校验和,大多数为10-100字节,很少高达1000。
但我真正想要的是更低级别的东西,一些SIMD的东西可以在128b寄存器上总结字节,或者可能在两个寄存器之间独立地求和字节而不携带进位,或两者兼而有之。
那里有没有这样的东西?
注意:这是实际的过早优化,但它很有趣,所以到底是什么?
编辑:我仍然需要一种方法来总结SSE寄存器中的所有字节,比
更好char ptr[16];
_mm_storeu_si128((__m128i*)ptr, sum);
checksum += ptr[0] + ptr[1] + ptr[2] + ptr[3] + ptr[4] + ptr[5] + ptr[6] + ptr[7]
+ ptr[8] + ptr[9] + ptr[10] + ptr[11] + ptr[12] + ptr[13] + ptr[14] + ptr[15];
答案 0 :(得分:2)
是的,MMX指令集中有这样的指令,称为“Packed ADD”:
_mm_add_pi8
__builtin_ia32_paddb
in gcc 在SSE2指令集中:
_mm_add_epi8
__builtin_ia32_paddb128
in gcc 编辑:添加部分总和的更快捷方式:
__m128i sums;
sums = _mm_add_epi8(sums, _mm_srli_si128(sums, 1));
sums = _mm_add_epi8(sums, _mm_srli_si128(sums, 2));
sums = _mm_add_epi8(sums, _mm_srli_si128(sums, 4));
sums = _mm_add_epi8(sums, _mm_srli_si128(sums, 8));
checksum += _mm_cvtsi128_si32(sums);
答案 1 :(得分:-1)
看看_mm_add_ps。同时添加128位连续块。您需要对数组进行零填充或处理最后几种非SIMD样式。