是否有SIMD指令来加速校验和计算
Are there SIMD instructions to speed up checksum calculations?
我将不得不编写一个非常基本的校验和函数,类似于:
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];
是的,在MMX指令集中有这样的指令,称为"打包ADD":
-
_mm_add_pi8
在Visual c++ -
__builtin_ia32_paddb
in gcc
在SSE2指令集中:
-
_mm_add_epi8
在Visual c++ -
__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);
查看_mm_add_ps。同时添加128位连续块。您需要对数组进行零填充或处理最后几个非SIMD样式。
相关文章:
- 如何用尽可能少的数据将数据缓冲区计算为零校验和值
- 计算校验和的逐位运算符
- 如何从存储在 QByteArray 中的十六进制值计算校验和
- 如何在 c++ 中计算对象的哈希/校验和/指纹?
- C++文件传输的校验和算法
- 如何从 IP 校验和字段中计算十六进制值
- 计算句子的校验和(XOR)(由不同变量/类型的组合形成)
- 目录校验和
- 编译后如何计算某些二进制功能(或基本块)的校验和
- PMS5003带有ESP8266-许多校验和错误
- 未正确的校验和释放对象 - 打印时错误
- 将C++校验和函数转换为 Java
- 确定是否使用boost.asio计算UDP校验和
- 校验和CRC 16从C 到Java
- 不同的CRC32校验和同一文件
- Qt,tcp/ip通信校验和
- 正在计算ICMP数据包校验和
- 错误的校验和错误遍布程序
- 如何计算 dmg 文件上的主校验和和数据分叉校验和
- 是否有SIMD指令来加速校验和计算