如何在运行时用C++区分Intel CPU各代?

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

SIMD 过去在 Intel CPU 上有初始化成本。因此,我正在寻找一种方法来在 C++ 运行时区分哪一代 Intel CPU 正在运行我的程序。

有没有一种简单的方法来区分所有早于Ice Lake的Intel CPU?

注意:检测运行的 CPU 是否为 Intel CPU 相当简单,但遗憾的是对于此用例来说还不够。

c++ x86 intel simd intrinsics
1个回答
0
投票

您可以让编译器在加载时使用编译器目标属性(或 GCC 所说的函数多版本控制)来计算出它,而不是在运行时手动检查 cpu 属性。

不幸的是,即使在“三大”编译器之间,它也不是标准功能,但 clang 和 gcc 至少提供了类似的实现。

这里有一个教程讨论了一些边缘情况的解决方法,但总的来说这应该是相当透明的。

您可以在 Github 上查看此代码,但基本上有两种方法可以实现。

首先使用

target
,您可以手动实现每个架构的版本

namespace detail {
inline Vector multiply(const Matrix& m, const Vector& v) {
    Vector r;
    r[0] = v[0] * m[0] + v[1] * m[2];
    r[1] = v[0] * m[1] + v[1] * m[3];
    return r;
}
}  // namespace detail

__attribute__((target("default"))) Vector multiply(const Matrix& m, const Vector& v) {
    printf("default\n");
    return detail::multiply(m, v);
}

__attribute__((target("arch=core2"))) Vector multiply(const Matrix& m, const Vector& v) {
    printf("core2\n");
    return detail::multiply(m, v);
}

__attribute__((target("arch=sandybridge"))) Vector multiply(const Matrix& m, const Vector& v) {
    printf("sandybridge\n");
    return detail::multiply(m, v);
}

如果所有实现在代码中都相似,那么当您选择所有可能的架构对其进行版本控制时,使用

target_clones
会更方便。

__attribute__((target_clones("default", "arch=core2", "arch=sandybridge", "arch=haswell", "arch=cascadelake",
                             "arch=znver1", "arch=znver2"))) Vector
multiply(const Matrix& m, const Vector& v) {
    Vector r;
    r[0] = v[0] * m[0] + v[1] * m[2];
    r[1] = v[0] * m[1] + v[1] * m[3];
    return r;
}) 

运行后,链接的代码将自动为您的目标机器选择正确的实现。

阅读更多:文档

© www.soinside.com 2019 - 2024. All rights reserved.