首页 > 解决方案 > 指向 AVX 加载结果的指针 (_mm256_load_si256)

问题描述

如果我有一些类的字段像__m256i* loaded_v,以及像这样的方法:

void load() {
    loaded_v = &_mm256_load_si256(reinterpret_cast<const __m256i*>(vector));
}

loaded_v有效指针将持续多长时间?由于寄存器数量有限,我想最终loaded_v会引用不同的值,或者会发生其他一些奇怪的行为。但是,我想减少我做的负载数量。

我正在编写一个打包位数组类,​​我想使用 AVX 内在函数来提高性能。然而,每次我做一些操作(和、或、异或等)时,加载我的位数组是低效的。因此,我希望能够load()在执行一些操作之前显式调用。但是,我不明白 AVX 寄存器是如何处理的。任何人都可以帮助我,或者指向我有关此问题的一些文档吗?

标签: sseintrinsicsavx2

解决方案


优化编译器会自动使用寄存器。

它可能将__m256变量放入内存或寄存器中,或者可能在代码的一部分中使用寄存器,并将其溢出到另一部分中。这不仅可以使用独立的自动存储(堆栈)变量来完成,还可以使用类的成员来完成,特别是如果类实例本身就是一个自动存储变量。

在使用寄存器的情况下,__m256变量将对应 ymm 寄存器之一(x86-64 中的 16 个,32 位编译中的 8 个之一,或 AVX512 的 x86-64 中的 32 个之一),无需间接引用它。

_mm256_load_si256内在不一定编译vmovdqa为. 例如,这段代码:

#include <immintrin.h>

__m256i f(__m256i a, const void* p)
{
    __m256i  b = _mm256_load_si256(reinterpret_cast<const __m256i*>(p));
    return _mm256_xor_si256(a, b);
}

编译如下(https://godbolt.org/z/ve67YPn4T):

        vpxor   ymm0, ymm0, YMMWORD PTR [rdx]
        ret     0

C 和 C++ 是高级语言;内在函数应该被视为向编译器传达语义的一种方式,而不是指令助记符。

您应该将值加载到变量中,

__m256i loaded_v;
loaded_v = _mm256_load_si256(reinterpret_cast<const __m256i*>(vector));

或临时:

__m256_whatever_operation(_mm256_load_si256(reinterpret_cast<const __m256i*>(vector)), other_operand);

您应该遵循通常的 C 或 C++ 规则。

如果您从指针重复加载间接值,将其缓存在变量中可能会有所帮助,以便编译器看到该值在加载之间没有变化,并将其用作优化机会。当然编译器无论如何都可能错过这个机会,或者即使没有缓存变量也能找到它(可能在严格的别名规则的帮助下)。


推荐阅读