AVX2(高级矢量扩展2)是x86的指令集扩展。它增加了256位版本的整数指令(其中AVX仅提供256b浮点)。
如何在 C (AVX2) 中向量化 int8 数组与 int16 常量的乘法,并扩展到 int32 结果数组
如何使用 AVX2 向量化这个 C 函数? static void propogate_neuron(const Short a, const int8_t *b, int *c) { 对于 (int i = 0; i < 32; ++i){ c[i] += a * b[i]; } } (Relat...
如何在AVX2中实现车道交叉逻辑按位移位(左移和右移)? 我想移动整个 __m256i,就好像它是一个 256 位整数,没有元素或通道边界。 一个答案...
我正在将使用 SSE2 内在函数编写的矢量化代码迁移到 AVX2 内在函数。 令我失望的是,我发现字节移位指令 _mm256_slli_si256 和 _mm256_srli_si256 运行
我实现了int8矩阵乘法的8位整数乘法。 这是我的代码,但我认为它真的很慢。 内联 __m512i int8_mul(__m512i a, __m512i b) { // 将向量 INT8 转换为 I...
我需要从每 24 位输入中解包两个 16 位值。 (3 字节 -> 4 字节)。我已经以幼稚的方式做到了,但我对表现不满意。 例如,InBuffer 是 __m128i: 价值...
我正在使用 AVX2 进行灰度到 BGRA 的转换。 灰度格式有点不寻常的是它是 16 位,但灰度值仅在较低的 8 位中,即它是 8 位数据
shuffling 的 api 仅支持 byte 和 sbyte // // 概括: // __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b) // // VPSHUFB ymm, ymm, ymm/m256 // // 参数: ...
这是代码: #包括 #包括 #包括 #包括 __m256i foo(); __m256i foo2(); int main() { __m256i vec1 = foo();
我想将 SSE/AVX 寄存器左移或右移 32 位的倍数,同时移入零。 让我更准确地说明我感兴趣的轮班。对于 SSE,我想做以下轮班......
给定一个包含 64 个 char 元素的 __m512i 向量: 索引:0、1、2、3、4、5、6、7、8、9、10、... 值:1、-1、1、0、0、-1、1、1、0、0、1、... (注:元素的值在[-1, 1]之间)....
我在 Windows 10 上使用 Visual Studio 2022。我的处理器:Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz 1.80 GHz。 这是代码: #包括 #包括 #包括 我在 Windows 10 上使用 Visual Studio 2022。我的处理器:Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz 1.80 GHz。 这是代码: #include <vector> #include <iostream> #include <time.h> using namespace std; void func(int* A, int na) { for (int k = 0; k < na; k++) for (int i = 0; i < na; i++) for (int j = 0; j < na; j++) A[j] = A[j] + 1; } int main() { int na = 5000; int* aint = new int[na]; func(aint, na); cout << aint[rand() % na]; delete[] aint; } MSVC 选项: cl /c /Zi /W3 /WX- /诊断:列 /sdl /O2 /Oi /GL /D NDEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /Gy /arch:AVX2 / Zc:wchar_t /Zc:forScope /Zc:inline /permissive- /Fo"x64\Release\" /Fd"x64\Release c143.pdb" /external:W3 /Gd /TP /FC /errorReport:prompt /Qvec-report :2 源码.cpp MSVC 不对 j 循环进行矢量化。由于代码 1300:“循环体包含很少或没有计算”,循环的日志未矢量化。 MSVC CPU 时间为 17 秒,由于 Intel Advisor 诊断,j 循环未矢量化。 Intel 2024 C/C++ 编译器 CPU 时间为 7 秒,由于 Intel Advisor 诊断,j-loop 通过使用 AVX2 指令进行矢量化。我是否遗漏了应该在 MSVC 选项中设置的内容,或者 MSVC 2022 在自动矢量化方面就是那么愚蠢?您能举一个 MSVC 使用自动矢量化的例子吗?对于我尝试过的所有示例,MSVC 不会矢量化。 我尝试指定不同的增强指令集,但都不起作用。 你的循环很奇怪;最好的优化是展开外部循环,这样就有一个循环可以完成 A[j] += na*na; 的任务。 如果您以这种方式编写源代码,我希望编译器能够自动矢量化。 使用当前源,Clang 会自动矢量化,无需重新排列循环,并且一次仅添加 1。 GCC 将两者混合用于独立的 func,其中 na 是运行时变量。 将 func 内联到 main 中时,GCC 不会自动矢量化,其中 na = 5000 是编译时常量。 但它交换了一些循环,因此它在内循环中执行 add edx, 4,以 sub eax, 2 / jnz 作为循环条件,以 eax=2500 作为内循环计数器开始。 它仅在中间循环中从数组加载和存储,加载提升/存储沉入内部循环。 (中间循环像源一样运行 5000 次迭代)。只有外部循环实际递增指针,因此在指针递增之间有 5000 次加载/存储同一数组元素。 (外部循环条件是一个指针与指向数组末尾一位的指针进行比较,来自 lea rdi, [rax+20000]) 在 func 的独立非内联版本中,GCC 将 k 或 i 展开 2 并在 j 上进行矢量化,而不交换任何循环,因此它在嵌套循环中执行 A[j + 0..7] += 2;,循环遍历每次通过内循环时 std::vector。 GCC 给 main 一个隐式的 __attribute__((cold)),但是当内联到 void foo() 时,我们得到与 int main() 相同的代码,所以关键的区别似乎是 na 是一个编译时常量,而不是cold 属性(减少优化和/或偏爱大小而不是速度)。 MSVC 确实使用 size_t j(使用 -O2 -arch:AVX2)进行自动矢量化,所以也许它无法证明 32 位 j 符号扩展到 64 位指针宽度? 希望 MSVC 确实知道 j < na 条件使循环绝对是非无限的,这样它就可以避免内部循环内的符号扩展。 在带有 MSVC 19.40 的 Godbolt 上 movsxd 中唯一的 func 指令位于函数顶部以进行符号扩展 na,内部循环使用 64 位 rcx 作为计数器(无缘无故) ;计数不能高于 2^31 - 1,这样 REX 前缀就会浪费代码大小)。 我链接了int版本;取消注释 size_t 行即可查看 asm。 (滚动到底部;由于包含 <iostream>,MSVC 吐出了很多东西。我还包含了 GCC 和 Clang -O2 -march=x86-64-v3,这相当于您的 MSVC 命令:使用 AVX2+FMA3+BMI1/2 进行全面优化) 其他编译器不关心 int 与 size_t j,除非在汇编中有我没有注意到的差异。
SIMD:减少/转换/投影/压缩/对齐 __m256i 到 __mmask8
我有一个 __m256i 寄存器,其中包含零/一值的打包 32 位整数: reg : [0 1 1 0 0 1 1 0] // 8 个整数的 256 位寄存器,每个整数为 0 或 1 我需要一个 SIMD 函数来转换 'r...
首先我想指出我糟糕的 C 技能 - 以及对 SIMD 指令的糟糕了解 - 所以我为我可能犯的任何愚蠢错误表示歉意。 这个问题与我的另一个问题有关
AVX2 代码,用于在 8 个 4 字节目标中查找 4 字节字符串的第一个最长匹配项
我需要最快的(即无分支、最小化微指令)相当于此代码的 AVX2 代码: 上一个长度 = 0 对于 i=0..7: len = matches_bytes(目标[i], src) 如果 len > prevlen: 上一个长度 = 长度 确实...
AVX2 代码用于在 8 个 4 字节目标中查找 4 字节字符串的最长匹配
我需要最快的(即无分支、最小化微指令)相当于此代码的 AVX2 代码: 上一个长度 = 0 对于 i=0..7: len = matches_bytes(目标[i], src) 如果 len > prevlen: 上一个长度 = 长度 确实...
如何使用 AVX 执行并行加法,并将进位(溢出)反馈到同一元素(PE 校验和)?
我想使用 AVX SIMD 执行 8 个 16 位值的并行加法。需要溢出加法,即“带进位加法”,就像使用旧的“adc”x86 助记符执行的那样。 我
我想使用 AVX SIMD 执行 8 个 16 位值的并行加法。需要溢出加法,即“带进位加法”,就像使用旧的“adc”x86 助记符执行的那样。 我
我正在尝试正确执行 SIMD AVX2 上的 6 位查找。我将这 6 位分成低 4 位和高 2 位,低 4 位用于洗牌操作,然后混合
如何在ARM NEON中实现_mm256_sign_epi8?
有没有方便的方法在NEON中实现x86的_mm256_sign_epi8(vpsignb)? 我想用 1 位来决定 NEON 中的 int8x16_t 向量是否否定或非否定。用 A 编码很容易...
我正在开发一个项目,需要在 C 中使用 AVX-512 减去分割成 32 位块的大整数。我当前的实现可以执行减法,但我在处理时遇到麻烦...