gpt4 book ai didi

c++ - g++ -O2 错误地优化了 SIMD 变量赋值

转载 作者:行者123 更新时间:2023-11-28 06:39:07 25 4
gpt4 key购买 nike

我正在使用英特尔 AVX2 指令编写程序。我在我的程序中发现了一个错误,该错误仅在优化级别为 -O2 或更高时出现(使用 -O1 很好)。经过大量调试后,我缩小了有问题的区域。现在这个错误似乎是由编译器错误地优化了 __m256i 变量的简单复制分配引起的。

考虑以下代码片段。 Foo 是一个模板函数。我使用 CMP = kLess, OPT=kSet 进行测试。我知道优化器可能会优化开关。它甚至可以优化变量 y

错误行是 y = m_lt;。当使用 -O2 编译时,此行似乎被忽略。然后 y 没有得到正确的值,程序产生了错误的结果。然而,程序是正确的 -O1。

为了验证我的判断,我将 y = m_lt; 替换为两个备选方案:

y = avx_or(m_lt, avx_zero());m_lt 和全 0 vector 进行按位或操作

y = _mm256_load_si256(&m_lt); 使用 SIMD 加载指令从 m_lt 地址加载数据。

两者在语义上应该等同于 y = m_lt; 我的意图是通过添加一些函数来防止某些优化。该程序在所有优化级别下都可以与这两个替换项一起正常工作。所以问题很奇怪。据我所知,SIMD变量直接赋值肯定没问题(我之前用的很多)。会不会是编译器的问题?

typedef __m256i AvxUnit;

template <Comparator CMP, Bitwise OPT>
void Foo(){
AvxUnit m_lt;
//...

assert(!avx_iszero(m_lt)); //always pass

AvxUnit y;

switch(CMP){
case Comparator::kEqual:
y = m_eq;
break;
case Comparator::kInequal:
y = avx_not(m_eq);
break;
case Comparator::kLess:
y = m_lt; //**********Bug?*************
//y = avx_or(m_lt, avx_zero()); //Replace with this line is good.
//y = _mm256_load_si256(&m_lt); //Replace with this line is good too.
break;
case Comparator::kGreater:
y = m_gt;
break;
case Comparator::kLessEqual:
y = avx_or(m_lt, m_eq);
break;
case Comparator::kGreaterEqual:
y = avx_or(m_gt, m_eq);
break;
}

switch(OPT){
case Bitwise::kSet:
break;
case Bitwise::kAnd:
y = avx_and(y, bvblock->GetAvxUnit(bv_word_id));
break;
case Bitwise::kOr:
y = avx_or(y, bvblock->GetAvxUnit(bv_word_id));
break;
}

assert(!avx_iszero(y)); //pass with -O1, fail with -O2 or higher

bvblock->SetAvxUnit(y, bv_word_id);
//...
}

最佳答案

编译器放弃赋值的原因可能是它认为该行代码是 代码。所以你的 CMP 不太可能是 Comparator::kLess

您尝试作为解决方法的分配可以使用 __asm__ volatile 语句来实现,并且它们无法优化。

m_lt 声明为 volatile 可能不会对您的性能产​​生太大影响,但修复它是一个肮脏的 hack。我会更多地关注 CMP 变量,看看它是否也可以采用 kLess 值。

关于c++ - g++ -O2 错误地优化了 SIMD 变量赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26274402/

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