使用 SSE / AVX 并行化 C 代码

Posted

技术标签:

【中文标题】使用 SSE / AVX 并行化 C 代码【英文标题】:Parallelize C Code using SSE / AVX 【发布时间】:2014-08-04 13:37:39 【问题描述】:

我想使用 SSE/AVX 命令并行化我现有的代码。 我完全是这些说明集的菜鸟

代码截图如下

static void inline enc_round(uint32_t b0[4], uint32_t b1[4], const uint32_t **kpp)

    for (int n = 0; n<4; n++)
    
        b0[n] = crypto_ft_tab[0][byte(b1[n], 0)] ^
            crypto_ft_tab[1][byte(b1[(n + 1) & 3], 1)] ^
            crypto_ft_tab[2][byte(b1[(n + 2) & 3], 2)] ^
            crypto_ft_tab[3][byte(b1[(n + 3) & 3], 3)] ^ *(*kpp + n);
    
    *kpp += 4;

具有以下类型定义

const uint32_t crypto_ft_tab[4][256]
static inline uint8_t byte(const uint32_t x, const unsigned n)

我想并行化逻辑 ANDS

编辑:对不起,我的意思是按位异或

任何建议什么是最好的启动方式或我应该启动哪些命令?

提前致谢

【问题讨论】:

我没有看到任何逻辑与 - 我看到按位异或 - 这就是你的意思吗? @PaulR 也许他的意思是(n + 1) &amp; 3 部分? 啊 - 按位 ANDs - 也许 - 这个问题需要澄清一下。 @PaulR vOv 是的...您可以编辑(再次 :) )以便问题更清楚(因为显然根本没有合乎逻辑的ands)。 当然 - 我只编辑了标签 - 我会让 OP 修复内容,因为我只是猜测真正的要求。 【参考方案1】:

在 GCC 和 Visual Studio 中,您可以轻松地使用编译器内部函数来生成 SSE 和 AVX 指令。

可在英特尔网站上找到可用指令列表:https://software.intel.com/sites/landingpage/IntrinsicsGuide/

使用 SSE2,这看起来像这样:

// load values 1 to 4 as 16 byte blocks from the given addresses:
__m128i value1 = _mm_loadu_((__m128i*)address1);
__m128i value2 = _mm_loadu_((__m128i*)address2);
__m128i value3 = _mm_loadu_((__m128i*)address3);
__m128i value4 = _mm_loadu_((__m128i*)address4);
// build xor
__m128i result = _mm_xor_si128(value1, value2);
result = _mm_xor_si128(result, value3);
result = _mm_xor_si128(result, value4);
// store the result somewhere into memory
_mm_storeu_si128((__m128i*)addressForResult);

请注意,每个 __m128i 变量都包含一个完整的 16 字节向量数据。使用 AVX2 内部函数,您甚至可以处理 32 字节块中的数据。

【讨论】:

以上是关于使用 SSE / AVX 并行化 C 代码的主要内容,如果未能解决你的问题,请参考以下文章

为啥并行 SIMD/SSE/AVX 需要置换?

使用 SSE 矢量化在 OpenMP 中将内部循环与残差计算并行化

使用 CUDA 在 C 中并行化基数排序的问题

我可以使用 OpenACC 并行化调用某些函数的大代码吗?

使用 OpenMP 在 C、C++ 中并行化嵌套 for 循环的几种方法之间的区别

AVX2 和 AVX-512 有啥区别?