如何在一个C++应用程序中支持多个SIMD架构?

问题描述 投票:0回答:1

我正在用 C++ 编写一个应用程序,我想使用 SIMD 的内在函数。 现在我想为不同的架构(如 SSE、AVX2 和 AVX512)编写单独的代码。 我可以在运行时检查支持哪些硬件并跳转到正确的实现。 问题是编译器需要了解它编译的架构。但我想添加不同架构的实现。 我该如何处理呢? 我可以为代码的不同部分添加编译器选项吗? 我使用带有 MSVC 编译器的 Visual Studio Code。我不想使用 SIMD 库来能够使用该库不支持的 SIMD 操作。

compiler-construction simd intrinsics
1个回答
0
投票

这有点复杂,但架构在编译时就已知。因此,您可以从包含正确的标题开始。如果您计划包含其他编译器或架构,请添加 mote

#elif
s

#if defined(_MSVC_LANG) && defined(_M_ARM64)
    #include <arm64_neon.h>
    #define ARCH_ARM64
#elif defined(_MSVC_LANG) && defined(_M_X64)
    #include <intrin.h>
    #define ARCH_X64
#else
    // TODO: Add support for other architectures
    #error "Unsupported architecture"
#endif

然后我们可以添加检测CPU功能并存储它们的代码,这样我们就不必在每次使用时都进行查询。

enum class isa_lvl: unsigned int
{
    none = 0,
    avx2 = 0x1,
    avx512 = 0x2,
    neon = 0x1001
};

isa_lvl g_isaLevel = isa_lvl::none;
void init_arch(void);


// TODO: call this once on startup
void init_arch(void)
{
    #if defined(ARCH_ARM64)
        g_isaLevel = isa_lvl::neon; // ARM64 always supports NEON
    #elif defined(ARCH_X64)
        int regs[4];
        __cpuidex(regs, 7,0); // use cpuid instruction to interrogate the CPU
        if (regs[1] & (1 << 16)) {
            g_isaLevel = isa_lvl::avx512;
        } else if (regs[1] & (1 << 5)) {
            g_isaLevel = isa_lvl::avx2;
        }
    #else
        // TODO: other archs
    #endif
}

最后,您可以在运行时使用缓存的 ISA 信息来调度最佳代码路径:

void do_stuff()
{
    switch (g_isaLevel)
    {
#if defined(ARCH_X64)
    case isa_lvl::avx2:
        do_stuff_avx2();
        break;
    //...
#elif defined(ARCH_ARM64)
    case isa_lvl::neon:
        do_stuff_neon();
        break;
#endif

    default:
        do_stuff_();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.