使用 AVX 逐个添加两个双精度数组
Entrywise addition of two double arrays using AVX
我需要一个函数来条目式添加两个双精度数组的元素并将结果存储在第三个数组中。目前我使用(简化)
void add( double* result, const double* a, const double* b, size_t size) {
memcpy(result, a, size*sizeof(double));
for(size_t i = 0; i < size; ++i) {
result[i] += b[i];
}
}
据我所知,memcpy函数使用AVX。为了提高性能,我还想强制使用 AVX 进行添加。这应该是AVX最基本的示例之一,但是我找不到任何描述如何在C
/C++
中执行此操作。如果可能的话,我想避免使用外部库。
假设 AVX-512,您将需要这样的东西:
void add( double* result, const double* a, const double* b, size_t size)
{
size_t i = 0;
// Note we are doing as many blocks of 8 as we can. If the size is not divisible by 8
// then we will have some left over that will then be performed serially.
// AVX-512 loop
for( ; i < (size & ~0x7); i += 8)
{
const __m512d kA8 = _mm512_load_pd( &a[i] );
const __m512d kB8 = _mm512_load_pd( &b[i] );
const __m512d kRes = _mm512_add_pd( kA8, kB8 );
_mm512_stream_pd( &res[i], kRes );
}
// AVX loop
for ( ; i < (size & ~0x3); i += 4 )
{
const __m256d kA4 = _mm256_load_pd( &a[i] );
const __m256d kB4 = _mm256_load_pd( &b[i] );
const __m256d kRes = _mm256_add_pd( kA4, kB4 );
_mm256_stream_pd( &res[i], kRes );
}
// SSE2 loop
for ( ; i < (size & ~0x1); i += 2 )
{
const __m128d kA2 = _mm_load_pd( &a[i] );
const __m128d kB2 = _mm_load_pd( &b[i] );
const __m128d kRes = _mm_add_pd( kA2, kB2 );
_mm_stream_pd( &res[i], kRes );
}
// Serial loop
for( ; i < size; i++ )
{
result[i] = a[i] + b[i];
}
}
(虽然请注意,我只是把它从我的头顶上扔了起来)。
从上面的代码中需要注意的是,我基本上使用下一个最佳并行代码处理剩余的值。 这主要是为了说明您可以并行执行的 3 种可能方法。 循环将自行完美运行。 例如,如果您不支持AVX-512,那么您将直接跳转到AVX循环。 如果您不支持 AVX,那么如果您直接跳转到 SSE2 循环,那么您将使用您的硬件可以支持的性能最高的循环。
为了获得最佳性能,您的阵列应与负载中使用的相关大小对齐。 因此,对于 AVX-512,您需要 512 位的 64 字节对齐。对于 AVX,256 位或 32 字节对齐。对于 SSE2 128 位或 16 字节对齐。 如果您对所有数组使用 64 字节对齐,那么您将始终具有良好的对齐方式,尽管您可能希望采用 128 字节对齐方式,以便在出现时轻松移动到 AVX-1024 ;)
相关文章:
- 我在C++中使用提升哈希函数将 3 个双精度组合成一个面临冲突的哈希
- 为什么在传递长整型时调用具有两个双精度类型的参数的重载函数?
- 为什么 2 个双精度值之间的差值计算错误?
- 宏定义中的预处理器令牌两边有两个双引号
- 在发布版本中划分两个双精度的结果错误
- 分配两个双精度值,保证产生相同的位集模式
- 有没有一种无分支方法可以快速找到两个双精度浮点值的最小值/最大值
- 如何将 4 个浮点数的 ps 向量转换为 4 个双精度并存储到 pd 数组
- 如何在 C/C++ 中有效地计算双倍到两个小数点精度
- 连接两个双矩阵
- 比较两个双精度值但结果很奇怪
- 两个双精度值的 C++ 比较无法正常工作
- 使用 AVX 逐个添加两个双精度数组
- 重载用于添加两个双链表的运算符
- 编写代码来检查两个双精度值是否足够不同
- 正、负两个双精度的比较
- 连接两个双变量
- 将长双精度对象存储在多个双精度变量中
- 包含两个双精度的类是 std::complex 参数的有效替代品<double>吗?
- c++中比较两个双精度值没有得到正确的结果