AVX512 使用的直方图制作

histogram making used by avx512

提问人:bjasku99 提问时间:9/13/2023 更新时间:9/13/2023 访问量:36

问:

我第一次尝试使用 avx512 指令并行实现直方图。 我的数据集是一个数组,其中包含从 0 到 255 的整数。(数组是对齐的),所以我的最终直方图数组包含 256 int,它应该表示每个亮度的像素数。 因此,为了实现并行解决方案,我制作了一个大 16 倍的数组(代码中的 16 = SIMD_WIDTH,这是 avx512 simd 寄存器中适合多少个 int32),以确保每个 simd 通道都对他自己的直方图区域进行内存事务处理,以避免内存冲突,这是代码运行良好。 当我尝试使用 avx512 将这些local_elements求和为最终直方图(在程序 local_hists 和 global_hist 中)时,问题就出现了。当我使用标量代码对它求和时,它运行良好。 所以这是我的 SIMD 代码:

for( int i = 0; i<SIMD_WIDTH; i++){
    for( int j = 0; j < hist_size ; j+=SIMD_WIDTH){
                _mm512_store_epi32( global_hist + j , _mm512_add_epi32( _mm512_load_epi32(global_hist + j) , _mm512_load_epi32(local_hists + (i*hist_size + j*SIMD_WIDTH)) ) );
    }
}

这是我的标量代码:

    for(int i = 0; i<SIMD_WIDTH; i++){
            for(int j = 0; j < hist_size;j++){
                global_hist[j]+=local_hists[i*hist_size + j];
            }
        }

hist_size = 256, SIMD_WIDTH = 16 ,所有数组都对齐 local_hists 数组是一个 16*256 长的 int 数组,前 256 个元素表示第一个 SIMD 通道直方图,接下来的 256 个元素表示第二个 SIMD 通道,依此类推。

我使用 gdb 来识别问题的位置,我发现,当我使用 SIMD 求和local_hists时会出现这种情况。 我尝试了一个标量代码,效果很好

AVX512系列

评论

1赞 Peter Cordes 9/13/2023
很难在一行上阅读所有这些内在函数的实际操作。什么问题?此外,您可以让编译器对标量代码进行矢量化;这应该可以有效地编译。另外,您提到 ,但您使用的是(32 位)内在元素?使用固定类型,如 ,而不是 Windows x64 与非 Windows x86-64 系统之间不同的类型。long intepi32uint32_t
1赞 Peter Cordes 9/13/2023
此外,您不想在内部循环中实际存储和重新加载,只需添加到您在最后存储一次的临时循环中即可。编译器可以可靠地对标量代码(如 )执行此操作,只要它们能够整理出别名并确保不与 重叠。但无论如何,对于冗长的内部函数代码,拥有临时代码更具可读性。顺便说一句,您实际上并不需要单独的存储空间,您可以简单地将存储到底部和(或)以返回未使用的空间。__m512iglobal_hist[j] += stuffglobal_histlocal_hists__m512i sumlocal_histsreallocstd::vector::shrink_to_fit

答: 暂无答案