gpt4 book ai didi

c++ - 现代 C++ 编译器是否自动矢量化代码以进行 24 位图像处理?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:30:37 24 4
gpt4 key购买 nike

gcc、visual studio c++、intel c++ 编译器、clang 等编译器是否像下面这样对代码进行矢量化?

std::vector<unsigned char> img( height * width * 3 );
unsigned char channelMultiplier[3];

// ... initialize img and channelMultiplier ...

for ( int y = 0; y < height; ++y )
for ( int x = 0; x < width; ++x )
for ( b = 0; b < 3; ++b )
img[ b+3*(x+width*y) ] = img[ b+3*(x+width*y) ] *
channelMultiplier[b] / 0x100;

32 位图像处理如何?

最佳答案

我认为您的三重循环不会自动向量化。 IMO 的问题是:

  • 通过对象类型 std::vector 访问内存。据我所知,我认为任何编译器都不会自动矢量化 std::vector 代码,除非访问运算符 [] 或 () 是内联的,但我仍然不清楚它是否会被自动矢量化。
  • 您的代码存在内存别名问题,即编译器不知道您引用 img 的内存是否是从另一个内存指针访问的,这很可能会阻止向量化。基本上,您需要定义一个普通 double 组并提示编译器没有其他指针指向同一位置。我认为您可以使用 __restrict 来做到这一点。 __restrict 告诉编译器这个指针是唯一指向该内存位置的指针,没有其他指针,因此没有副作用的风险。
  • 默认情况下内存未对齐,即使编译器设法自动向量化,未对齐内存的向量化也比对齐内存慢很多。您需要确保您的内存是 32 位内存地址对齐以最大程度地利用自动矢量化和 AVX 和 16 位地址对齐以最大程度地利用 SSE,即始终对齐 32 位内存位地址。您可以通过以下方式动态执行此操作:

    double* buffer = NULL;
    posix_memalign((void**) &buffer, 32, size*sizeof(double));
    ...
    free(buffer);

在 MSVC 中,您可以使用 __declspec(align(32)) double array[size] 执行此操作,但您必须检查您正在使用的特定编译器,以确保您使用的是正确的对齐方式指令。

另一件重要的事情,如果您使用 GNU 编译器,请使用标志 -ftree-vectorizer-verbose=6 来检查您的循环是否正在自动矢量化。如果您使用 Intel 编译器,则使用 -vec-report5。请注意,有多个级别的冗长和信息输出,即 6 和 5 数字,因此请查看编译器文档。详细级别越高,您将为代码中的每个循环获得的矢量化信息越多,但编译器在 Release模式下编译的速度越慢。

总的来说,我一直很惊讶让编译器自动向量化是多么不容易,一个常见的错误是认为因为循环看起来是规范的,所以编译器会自动神奇地自动向量化它。

更新:还有一件事,确保您的 img 实际上是页面对齐的 posix_memalign((void**) &buffer, sysconf(_SC_PAGESIZE), size*sizeof(double)) ;(这意味着 AVX 和 SSE 对齐)。问题是,如果你有一个大图像,这个循环很可能会在执行期间结束页面切换,而且这也非常昂贵。我想这就是所谓的TLB错过。

关于c++ - 现代 C++ 编译器是否自动矢量化代码以进行 24 位图像处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11913512/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com