首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么用于迭代的不同类型的数组下标会影响自动矢量化

为什么用于迭代的不同类型的数组下标会影响自动矢量化
EN

Stack Overflow用户
提问于 2022-06-25 04:45:16
回答 1查看 86关注 0票数 4

如下代码所示,为什么uint32_t阻止编译器(GCC 12.1 + O3)通过自动矢量化进行优化。见哥德波特

代码语言:javascript
复制
#include <cstdint>

// no auto vectorization
void test32(uint32_t *array, uint32_t &nread, uint32_t from, uint32_t to) {
    for (uint32_t i = from; i < to; i++) {
        array[nread++] = i;
    }
}

// auto vectorization
void test64(uint32_t *array, uint64_t &nread, uint32_t from, uint32_t to) {
    for (uint32_t i = from; i < to; i++) {
        array[nread++] = i;
    }
}

// no auto vectorization
void test_another_32(uint32_t *array, uint32_t &nread, uint32_t from, uint32_t to) {
    uint32_t index = nread;
    for (uint32_t i = from; i < to; i++) {
        array[index++] = i;
    }
    nread = index;
}

// auto vectorization
void test_another_64(uint32_t *array, uint32_t &nread, uint32_t from, uint32_t to) {
    uint64_t index = nread;
    for (uint32_t i = from; i < to; i++) {
        array[index++] = i;
    }
    nread = index;
}

在运行命令g++ -O3 -fopt-info-vec-missed -c test.cc -o /dev/null之后,我得到了以下结果。怎么解释呢?

代码语言:javascript
复制
bash> g++ -O3 -fopt-info-vec-missed -c test.cc -o /dev/null
test.cc:5:31: missed: couldn't vectorize loop
test.cc:6:24: missed: not vectorized: not suitable for scatter store *_5 = i_18;
test.cc:21:31: missed: couldn't vectorize loop
test.cc:22:24: missed: not vectorized: not suitable for scatter store *_4 = i_22;
EN

回答 1

Stack Overflow用户

发布于 2022-06-25 06:38:35

看看这个函数

代码语言:javascript
复制
void test32(uint32_t *array, uint32_t &nread, uint32_t from, uint32_t to)

如果你这样称呼它,它应该如何表现:

代码语言:javascript
复制
uint32_t arr[16];
test32(arr, arr[3], &arr[0], &arr[15]);

这叫做混叠。nread参数可能会别名来自array的元素,因为它们具有相同的类型。但当你有

代码语言:javascript
复制
void test64(uint32_t *array, uint64_t &nread, uint32_t from, uint32_t to)

这样就不会出现混叠,因为uint32_tuint64_t永远不会有相同的地址。

注意:传递对函数的引用在内部传递地址,因此它相当于别名参数的指针。

有一些特殊规则的类型称为混叠类型。C++标准说,您可以将uint32_t*强制转换为char*,然后访问uint32_t底层的原始内存。这意味着uint32_t*char*可以合法地指向同一个地址。char*是一种别名类型,因为它与任何其他类型的(数据)指针别名。unsigned char*或包括std::byte在内的char的任何其他变体也是如此。

但是,您可以告诉编译器,即使类型允许使用限制,也不允许有2个指针别名。

代码语言:javascript
复制
void test32(uint32_t *array, uint32_t & restrict nread, uint32_t from, uint32_t to)

PS:test_another_32看起来像是一个漏掉的编译器优化。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72751322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档