如何在不影响性能的情况下抽象 SIMD 代码以处理不同的数据类型

Posted

技术标签:

【中文标题】如何在不影响性能的情况下抽象 SIMD 代码以处理不同的数据类型【英文标题】:How to Abstract SIMD code to handle different datatypes without a performance hit 【发布时间】:2018-04-28 19:26:00 【问题描述】:

我一直在编写执行矩阵运算的代码。最初它仅适用于 x86,现在正在将其移植到不同的体系结构。另外,我希望它支持浮点以外的不同数据类型。

考虑以下添加到浮点数组的代码

void add(float *a, float *b, float *dst, int len)

        int k = 0;
        for(; k + 8 <  len; k += 8,a +=  8, b += 8, dst+= 8)
            __m256 x = _mm256_load_ps(a);
            __m256 y = _mm256_load_ps(b);
            __m256 z = _mm256_add_ps(x, y);
            _mm256_store_ps(dst, z);
        

这是我想到的改进代码以支持多种平台和数据类型的想法。

    针对不同的数据类型,我打算把函数改成模板函数

    对于 simd 指令,我想到了使用宏将所有特定于体系结构的内在函数重命名为通用 simd 指令,例如 SIMD_ADD 。问题是不同的数据类型需要不同的内在函数,而内在函数的返回类型也取决于数据类型。

    另外,如果我要编写减法函数,我最终会复制大部分代码,只是为了将 SIMD_ADD 宏替换为 SIMD_SUB 宏。它们是否是一种简洁的方式,这样我就不必为所有元素明智的操作(如乘法、除法和减法)重复相同的代码?

如果不抽象到影响代码性能的程度,如何处理第 2 点和第 3 点?

【问题讨论】:

我完全忘记了在 c++11 中引入的 auto。因此第 2 点不再是问题 目前可能没有任何帮助,但C++20可能有support for this。 【参考方案1】:

我最终获得了用于 simd 指令的模板类,并针对每种数据类型进行了专门化。不幸的是,编译器不会自动内联它,因此您必须使用编译器特定的属性来强制它内联

【讨论】:

以上是关于如何在不影响性能的情况下抽象 SIMD 代码以处理不同的数据类型的主要内容,如果未能解决你的问题,请参考以下文章

如何在不完全影响主屏幕绘图性能的情况下每 200/250 毫秒更新一次小部件?

在不使用受保护的情况下处理抽象类的正确方法是啥?

ASP.NET MVC:在不影响性能的情况下路由自定义 slug

在不使结构只读的情况下避免使用带有结构的“in”对性能造成的影响?

如何在不轮询的情况下监视页面的更改?

SIMD 在这种情况下表现如何?