【问题标题】:-fno-strict-aliasing as function attribute-fno-strict-aliasing 作为函数属性
【发布时间】:2016-04-01 17:48:19
【问题描述】:

我有一个函数,出于性能原因,我在其中键入双关语。基本上,我有一个 32×32 位数组存储为 32 个 uint32s 的数组:

struct Tile {

    uint32_t d[32];

};

然后我想计算 32×32 瓷砖的 28×28“内部”的人口(“1”的数量)。简单的方法需要 28 次调用机器的 popcnt 指令,每行一个。但是,由于 popcnt 可以采用 64 位参数,因此可以减少到 14 个 popcnt 调用:

int countPopulation(Tile* sqt) __attribute__((optimize("-fno-strict-aliasing"))) {

    int pop = 0;

    for (int i = 2; i < 30; i += 2) {
        const uint64_t v = *reinterpret_cast<const uint64_t*>(sqt->d + i);
        pop += __builtin_popcountll(v & 0x3ffffffc3ffffffcull);
    }

    return pop;

}

如果我不包含属性:

__attribute__((optimize("-fno-strict-aliasing")))

那么 g++ 会出于明显的原因不断抱怨我的类型双关语:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
         const uint64_t v = *reinterpret_cast<const uint64_t*>(sqt->d + i);

另一方面,如果我包含该属性,某些版本的 g++ 会抱怨,而其他版本则不会。在我尝试过的机器中,我得到:

  • g++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4 抱怨
  • g++-4.6.real (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 不抱怨
  • g++ (Debian 5.3.1-5) 5.3.1 20160101 不抱怨

g++ 4.8.4 的 Ubuntu 风格有什么问题?

【问题讨论】:

  • 出于性能原因,我在打双关语——这里是个谬论。

标签: c++ ubuntu gcc g++


【解决方案1】:

不要打字。没有理由这样做。而是正确使用 memcpy() 复制到您的 int64_t 参数。优化器将完成剩下的工作。

【讨论】:

  • 谢谢,你是对的。我使用 std::memcpy 和 reinterpret_cast 生成了汇编代码,它们是相同的。
  • @AdamP.Goucher,当然是。你看,优化器是由开发人员为开发人员编写的,而不是由一些想要让我们的生活难以忍受的外星怪物:D
  • 任何人在 1989 年建议一个体面的编译器应该强制程序员使用 memcpy 来避免别名限制,如果没有完全回避的话,他们会被嘲笑。该标准的目的是避免要求编译器在没有理由期望指向别名的指针的情况下对别名做出悲观的假设——而不是忽略代码获取对象地址并使用结果指针 的情况通过任何类型来访问存储在下一次访问相关对象之前。一些编译器作者很迟钝...
  • ...但我没有理由支持 memcpy 在进入函数之前(如果它使用外来指针读取)和/或在它退出之前(如果它使用外来指针写入)作为别名屏障。 Memcpy 不像以前那么狗了,但这并不意味着它总是像简单的代码一样快,而且它肯定会变得不那么易读。
  • @supercat,即使您不同意标准,否决我的回答也是不公正的。不是我写的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 2021-04-09
  • 1970-01-01
相关资源
最近更新 更多