使用 SSE 的乘法 (x*x*x)+(y*y*y)
我正在尝试使用SIMD来优化此功能,但我不知道从哪里开始. long sum(int x,int y) { return x*x*x+y*y*y; } 拆卸功能看起来像这样: 4007a0: 48 89 f2 mov %rsi,%rdx 4007a3: 48 89 f8 mov %rdi,%rax 4007a6: 48 0f af d6 imul %rsi,%rdx 4007aa: 48 0f af c7 imul %rdi,%rax 4007ae: 48 0f af d6 imul %rsi,%rdx 4007b2: 48 0f af c7 imul %rdi,%rax 4007b6: 48 8d 04 02
36 2024-04-22
编程技术问答社区
将 __m128i 中的每个 DW 右移不同的量
我想以其他数量向右移动__m128i寄存器的每个元素. __m128i mul_constant = _mm_set_epi32(8, 4, 2, 1); __m128i left_vshift = _mm_mullo_epi32(R, mul_constant); ,但是,如果我们想正确地移动它的解决方案是什么? 解决方案 我终于做到了以下内容: 将每个字节转移到左侧的不同数量,然后将32位的右移动换成3,这给了我我想要的. R = _mm_mullo_epi32(R, _mm_set_epi32(1, 2, 4, 8)); R = _mm_srli_epi32(R, 3);
24 2024-04-22
编程技术问答社区
以可移植方式访问 __m128i 变量的字段
我正在尝试使用SIMD指令来加快UINT8_T数组(即减少总和)中的元素之和.为此,我在这个问题中复制了最投票的答案: sum使用Intel上的SSE2降低无溢出的无符号字节 该答案中显示的总和减少的过程是: uint16_t sum_32(const uint8_t a[32]) { __m128i zero = _mm_xor_si128(zero, zero); __m128i sum0 = _mm_sad_epu8( zero, _mm_load_si128(reinterpret_cast(a))); __m128i sum1 = _mm_sad_epu8( zero, _mm_load_si128(reinterp
20 2024-04-22
编程技术问答社区
谁能解释一下这个 SSE BigNum 比较?
如果您查看此答案,作者设法为2个整数Bignums创建了一个紧凑的比较算法,存储在2个SSE寄存器中.我不太关注它:) 我到目前为止所做的: 如果l = a b1) 在我的问题中,我的目标是用SSE/AVX寄存器实施任意长的Bignums.
22 2024-04-22
编程技术问答社区
如何将矢量中的数值相加
在我的代码中,我解决了积分 y=x^2-4x+6 我使用了SSE-它允许我一次对4个值进行操作.我制作了程序,该程序以0到5的值求解该积分,分别为五个4元素向量n1,n2,n3,n4. .data n1: .float 0.3125,0.625,0.9375,1.25 n2: .float 1.5625,1.875,2.1875,2.5 n3: .float 2.8125,3.12500,3.4375,3.75 n4: .float 4.0625,4.37500,4.6875,5 szostka: .float 6,6,6,6 czworka: .float 4,4,4,4 .text .global main main: movups (n1),%xmm0 mulps %xmm0,%xmm0 movups (szostka),%xmm2 addps %xmm2,%xmm0 movups
8 2024-04-22
编程技术问答社区
在 XMM 寄存器中取消引用指针(收集)
如果我有一些指针或指针式值包装到SSE或AVX寄存器中,是否有任何特别有效的方法将它们放在另一个这样的寄存器中? ("特别有效"的意思是"比仅将内存用于值更有效". 编辑以进行澄清:这意味着,假设有32位指针和SSE,将XMM寄存器的四个部分一次索引到四个任意内存区域,并立即将四个结果返回到另一个寄存器.或尽可能接近"一次". (/编辑) edit2:感谢Paulr的答案,我猜我要寻找的术语是"收集",因此问题是"实施系统pre-avx2的最佳方法是什么?". 我认为没有任何指示,因为...嗯,我似乎并不存在,无论如何,似乎根本不是SSE的设计. ("像指针般的价值",意思是一个像整数索引成一个阵列,假装是堆;在机械上非常不同,但在概念上是相同的东西.如果有人想使用32位甚至16位值不管本机指针大小如何,以适合寄存器中的更多值.) 我可以想到为什么有人想这样做的两个可能的原因: 认为,使用SSE寄存器进行通用...东西探索可能很有趣,也许可以使用四个相同的"线
20 2024-04-22
编程技术问答社区
使用 SIMD 查找字节数组中未对齐 int 或 long 的索引
我有一个字节序列,我想扫描以找到整数(或long)值的索引.它可以处于任何字节偏移量,不一定是大小的倍数.具体来说,我对第一次事件感兴趣,但所有索引的示例也将有所帮助. 如果不可能,我想我需要将长时间转换为8个字节长度,而不是比较两个. 平台为x86.我可以约束应用程序仅运行x64模式. 我需要最快的方法,以便代码段很棒. 我知道这是一个简单的问题,但找不到一个例子(至少在C#中). 解决方案 阅读此 static void Main(string[] args) { var input = "12345671asdasdasd1asdasdasd2asdasdasd3asdasdasd_12345678asdasdasd1asdasdasd2asdasdasd3asdasdasd_"u8; var needle = BitConverter.ToInt64("12345678"u8); var ix = IndexOf(input, needle); } pub
10 2024-04-22
编程技术问答社区
如何使用 simd 将 uint32 转换为 uint8,但不使用 avx512?
说,在对齐内存uint32 *p中有很多UINT32S商店,如何使用SIMD转换为UINT8? 我看到有_mm256_cvtepi32_epi8/vpmovdb,但它属于avx512,而我的CPU不支持它😢 解决方案 如果您真的有很多,我会做这样的事情(未经测试). 主循环读取包含16个UINT32_T值的64个字节,围绕实现截断的字节围绕的字节散装,将结果合并为单个寄存器,并使用Vector Store Orcession撰写16个字节. . void convertToBytes( const uint32_t* source, uint8_t* dest, size_t count ) { // 4 bytes of the shuffle mask to fetch bytes 0, 4, 8 and 12 from a 16-bytes source vector constexpr int shuffleScalar = 0x0C
16 2024-04-22
编程技术问答社区
如何获取英特尔架构 SIMD __m128 的符号?
因为" _mm_sign_ps"在我所能找到的情况下不存在:给定一个带有四个浮点值的__m128值,SIMD指令或SIMD指令的列表将其转换为__-M128值,带有四个Floating-包含的点值: +1,如果四个的原始值是正的,大于零. 0,如果四个的原始值为零. -1,如果四个的原始值为负,小于零. 解决方案 SSE确实根本不太匹配.首先,比较函数不会导致±1.0F,而是如果条件为真,则设置所有位,或者如果条件为false,则没有设置它们.另外,如果值为"零",则您要进行三路比较,而结果为"零"("零"为"零",因为您实际上没有指定您是要零还是负零; ieee 754两者都有).如果您可以重新构架问题以更好地匹配SSE提供的内容,那么您将成为很多. 也就是说: __m128 foo (__m128 value) { const __m128 zero = _mm_set_ps1 (0.0f); __m128 positives = _mm_and_
26 2024-04-22
编程技术问答社区
有没有将 __m128i 向量最后 n 个字节清零的固有函数?
给定n,我想归零__m128i向量的最后一个n字节. 例如,考虑以下__m128i向量: 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 归零最后一个n = 4字节后,向量应看起来像: 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00000000 00000000 00000000 00000000 是否有SSE内在函数可以执行此操作(通过接受__128i向量和n作为参数)? 解决方案 有多种不依赖AVX512的选项.例如: 不重组
6 2024-04-22
编程技术问答社区
如何使用 SIMD 检查偶数/奇数通道是否在给定范围内?
给定__m128i存储16 char s的__m128i,偶数巷是指 em> em em> lane(即,在0、2、4,...,...,14)的车道(即和奇数巷是指奇数巷道(即,车道在1、3、5,... 15). 在我的应用程序中,甚至在给定的范围内都必须处于范围.例如,假设even_min是1,even_max是7,odd_min是5,而odd_max是10: # valid vec1: [1, 5, 6, 10, 2, 6, 4, 6, 2, 7, 4, 9, 2, 7, 4, 8] # invalid because 0-th (even) is greater than even_max vec2: [8, 5, 6, 10, 2, 6, 4, 6, 2, 7, 4, 9, 2, 7, 4, 8] 如何检查它是否有效更有效? 分别检查两个比较结果,我当前的解决方案非常简单: __m128i even_min = _mm_set1_epi8(xx
12 2024-04-22
编程技术问答社区
使用 x64 SIMD 进行位元洗牌
我知道 解决方案 使用必须以这种方式存储的控制向量的任意洗牌? gh,很难与之合作.我想你必须拆开两个以进食ssse3 pshufb,然后重新包装结果. 可能只是punpcklbw对右移副本,然后掩盖每个字节中仅保留低4位.然后pshufb. 有时奇数/偶数比扩大每个元素更容易(因此位仅留在其原始字节或单词中).在这种情况下,如果我们可以更改您的nibble索引编号,punpcklqdq可能会将奇数甚至nibbles放在高级中,准备将它们放回和. . 但没有这样做,重新包装是一个单独的问题.我想将相邻的字节对组合到低字节中的一个单词,也许与 pmaddubsw pmaddubsw 吞吐量比潜伏期更重要.然后,您可以 packuswd (反对零或自身)或pshufb(具有恒定的控制向量). 如果您正在进行多次这样的混音,则可以将两个向量装箱到一个,以使用movhps/movq存储.使用AVX2,可能会使所有其他指令在两个128位车道中的两个独立的散装上工作.
14 2024-04-22
编程技术问答社区
用汇编求浮点数组的和
我正在从C程序中调用的汇编X86中实现一个函数,以添加float数组.该函数的第一个参数是指向数组的指针,第二个是元素数.当我在Linux中运行代码时,我会得到一个细分故障.我做错了什么? .text .globl floatsum floatsum: push %ebp movl %esp, %ebp movl 8(%ebp), %eax movl 12(%ebp), %edx shrl $2, %edx xorps %xmm0, %xmm0 loop: testl %edx, %edx je end movaps (%eax), %xmm1 addps %xmm1, %xmm0 addl $16, %eax decl %edx jmp loop end: # 3 2 1 0 movaps %xmm0, %xmm1 # xmm0: w
22 2024-04-22
编程技术问答社区
使用 SIMD 对字节矢量进行解交织
我的输入向量为16384,签名了四个整数.它们被包装成8192个字节.我需要将值交换并在两个单独的数组中拆开8位整数. a,b,c,d是4位值. a,b,c,d是8位值. input = [ab,cd,...] out_1 = [a,c,...] out_2 = [b,d,...] 我可以在C ++中很容易做到这一点. constexpr size_t size = 32768; int8_t input[size]; // raw packed 4bit integers int8_t out_1[size]; int8_t out_2[size]; for (int i = 0; i > 4; out_2[i] = input[i] >> 4; } 我想实施此功能以尽可能快地在通用处理器上操作.良好的S
18 2024-04-22
编程技术问答社区
如何在 MSVC 中启用 SSE4.1 和 SSE3(但不包括 AVX
我试图使用MSVC启用不同的SIMD支持. 有一个页面谈论启用一些simd,例如sse2,avx,avx2 但是,它没有提及如何启用其他SIMD优化,例如SSE4.1,SSE4.2,SSE3 是否可以在不启用AVX的情况下启用这些? 另外,在MSVC2017/Arch中看起来不再支持/需要SSE2,我可以假设SSE3/sse4.1/sse4.2默认启用了吗? 解决方案 显然您可以以/d2...选项的方式传递/arch:选项.像/d2archAVX. /d2archSSE42是这样接受的(而不是SSE41或SSE3). @peter在评论中指出了/d2archSSE42有所作为的情况: https://godbolt.org.org.org/z/esjw4vtne 其他解决方案 VC ++编译器的智能不如您想象的.这些设置是如何工作的. 当您构建32位代码并启用SSE1或SSE2时,它启用自动矢量化到各自的说明集. 当您构建64位代码时,
22 2024-04-22
编程技术问答社区
将数据存入 SIMD 寄存器需要多少个周期?
我是一个学习X86和Arm Architecture的学生. 我想知道将多个数据放入SIMD寄存器需要多少周期? 我知道X86 SSE的XMMS寄存器具有128位寄存器的大小. 如果我想通过SIMD指令集和汇编语言将8位8位数据中的32个数据放入XMMS寄存器之一, 通用寄存器的推送/pop的周期时间相同? 或每个8位数据需要32倍的时间? 谢谢您的关注和关注! 解决方案 简短答案: 如果您正在使用Sandy Bridge,Ivy Bridge和Haswell和Haswell,或使用Nahelem . Nahelem之前的处理器取决于您是否进行对齐负载或未对准负载. 长答案: Mystical向您提供了所需的信息,请您要查看的指令是:MOVDQU和MOVDQA,带有操作数X,M128.这两者都将在一个操作中加载128位数据中的XMM/YMM寄存器. MOVDQA要求该地址由16个字节对准. MOVDQU没有这样的限制.
20 2024-04-22
编程技术问答社区
在使用 pshufb 洗牌作为 nibbles 的查找表之前,为什么需要屏蔽?
此代码来自std::uint64_t popcnt_AVX2_lookup(const uint8_t* data, const size_t n) { size_t i = 0; const __m256i lookup = _mm256_setr_epi8( /* 0 */ 0, /* 1 */ 1, /* 2 */ 1, /* 3 */ 2, /* 4 */ 1, /* 5 */ 2, /* 6 */ 2, /* 7 */ 3, /* 8 */ 1, /* 9 */ 2, /* a */ 2, /* b */ 3, /* c */ 2, /* d */ 3, /* e */ 3, /* f */ 4, /* 0 */ 0, /* 1 */ 1, /* 2 */ 1, /* 3 */ 2, /* 4 */ 1, /* 5 */ 2, /* 6 */ 2, /* 7 */ 3, /* 8 */ 1, /* 9 */ 2, /* a */ 2, /* b */ 3, /* c */ 2,
12 2024-04-22
编程技术问答社区
在 SIMD 运算中,非打包指令和打包指令有什么区别?
在SIMD操作的上下文中,未包装和包装指令有什么区别? 我正在阅读一篇有关优化您的SSE代码的文章: /a> 我阅读 时出现了这个问题 "作为额外的奖励,Movss是一项未包装的指令,它使我们能够更好地利用并行指令解码器." 那么有什么区别? 解决方案 对我的理解,包装是指从概念上转移或用作操作数的一个以上的值,而 无包装表示只有一个值是已处理; 不包装表示没有进行并行处理. 其他解决方案 SSE支持两种操作模式: 包装模式 - 指令在所有数据操作数上并行操作 标量模式 - 指令以最不重要的包装数据操作数对操作. source source
16 2024-04-22
编程技术问答社区
使用 SIMD 计算行列式
是否存在一种方法来计算较低尺寸的矩阵的决定因素(约4),与SIMD(NEON,SSE,SSE2)效果很好?我正在使用手动膨胀公式,该公式的工作不佳.我一直在Linux下使用SSE到SSE3和NEON.矩阵元素都是浮子. 解决方案 这是我的5美分. 2x2矩阵的决定因素: 这是读者的练习,应该易于实现 3x3矩阵的决定因素: 使用标量三重产品.这将需要SMART cross()和dot()实现.这些食谱广泛可用. 4x4矩阵的决定因素: 在中.我的代码: template inline T det(matrix const& m) noexcept { auto const A(make_matrix(m(0, 0), m(0, 1), m(1, 0), m(1, 1))); auto const B(make_matrix(m(0, 2), m(0, 3),
20 2024-04-22
编程技术问答社区