MaskStore在幕后做什么?
我的主要编程语言是C#,最近我一直在尝试学习矢量编程和Intel X86 AXV2上的一些SIMD说明,以进行自学习.我遇到了指令VPMASKMOVD m256, ymm, ymm 我只是想知道该指令在幕后如何工作,以伪代码进行编程的是: for n in vector.values if (highest bit of mask is set for vector n) { address = source vector[n] } 解决方案 是的,这是正确的. ASM手册 com/x86/vmaskmov#vmaskmovpd ---- 256位商店用类似的伪代码记录了它.英特尔的C/C ++内在指南的详细信息较少但类似的文档:请注意,这是AVX1指令,而不是AVX2.自从桑德布里奇(Sandybridge)在英特尔(Intel)上获得支持,自推土机以来,AMD. 在AMD CPU上不是很有效,尽管按照 https:
20 2024-04-24
编程技术问答社区
使用 ARM-v8 Neon SIMD 将 ascii 字符串比特包转换为 7 位二进制数据块
按照我的 x86问题,,我想知道如何有可能在ARM-V8上有效地对以下代码进行矢量化: static inline uint64_t Compress8x7bit(uint64_t x) { x = ((x & 0x7F007F007F007F00) >> 1) | (x & 0x007F007F007F007F); x = ((x & 0x3FFF00003FFF0000) >> 2) | (x & 0x00003FFF00003FFF); uint64_t res = ((x & 0x0FFFFFFF00000000) >> 4) | (x & 0x000000000FFFFFFF); /* does the following: uint64_t res = (x & 0xFF); for (unsigned i = 1; i >= 1; res |= (x & (0x7FUL
28 2024-04-22
编程技术问答社区
如何将 8 个打包的 32 位整数(在 __m256i 中)的 +-1 符号打包成 64 位整数的字节?
给定一个价值的__m256i包装的32位签名整数,如果来自原始__m256i的相应32位签名的整数大于相应的32位签名的整数,则如何获得单个64位编号.或等于0,并获得-1如果该32位整数为负? avx2(可能是AVX512)很感兴趣. 解决方案 这是另一种方法. 它需要BMI2支持PDEP指令,仅在Intel上快速,并且以Zen 3 Microharchituctor开头. // Convert sign bits of 8 int32 lanes into -1 / +1 bytes uint64_t packSigns( __m256i vec ) { // Bitcast to FP32 vector, compiles into no instructions __m256 fv = _mm256_castsi256_ps( vec ); // Move sign bits to general-purpose register
30 2024-04-22
编程技术问答社区
使用 SIMD 将 ascii 字符串比特包转换为 7 位二进制数据块
相关: bitppack使用ARM-V8 NEON SIMD - ASCII将ASCII串入7位二进制斑点 - 专门用于AARCH64内在的问题.这个问题涵盖了便携式C和X86-64内在. 我想将一个char字符串编码为7位斑点,以减少记忆的12.5%. 我想尽可能快地这样做,即编码大字符串时的延迟最小. 这是算法的简单实现: void ascii_pack(const char* ascii, size_t len, uint8_t* bin) { uint64_t val; const char* end = ascii + len; while (ascii + 8
24 2024-04-22
编程技术问答社区
如何高效地实现四个 i8 元素组的 _mm256_madd_epi8 点积?
英特尔提供了名为_mm256_madd_epi16的C样式功能,基本上是 __ m256i _mm256_madd_epi16(__m256i a,__m256i b) 在A和B中乘以填充的16位整数,产生中间签名的32位整数.水平添加相邻的成对中间32位整数,并将结果包装在dst. 中 现在我有两个__m256i变量,每个变量都有32个8位int. 我想实现与_mm256_madd_epi16相同的功能,但是结果__m256i中的每个int32_t元素是四个签名char的产品的总和,而不是两对签名int16_t..每个32位块中的四个int8_t元素的点产物. 我可以在标量循环中做到这一点: alignas(32) uint32_t res[8] = {0}; for (int i = 0; i
12 2024-04-22
编程技术问答社区
x86 SIMD 内核的参考手册/教程?
我正在考虑使用它们来提高某些代码的性能,但是对于*mmintrin.h标题中定义的功能似乎很难找到好的文档,任何人都可以为我提供有关这些功能的指示器吗? 编辑:特别对一个关于如何入门的非常基本的教程感兴趣. 解决方案 有一个方便的在线 Intel Intersics指南 https://www.intel.com/content/www/www/us/en/en/docs/intrinsics-guide/index.html - 它涵盖了所有Intel Simd的东西MMX通过SSE的各种口味,直至Avx2 et al . 您还可以从 intel "> intel : Intel®64和IA-32体系结构软件开发人员手册,第2A卷:指令集参考,A-M(253666-021) Intel®64和IA-32体系结构软件开发人员手册,第2B卷:指令集参考,N-Z(253667-021) intel®SSE4编程参考(D91561-001) 其他解决
16 2024-04-22
编程技术问答社区
"_mm256_set1_epi64x "等本征函数中后缀 "x "的含义
在某些内在物质中,他们使用后缀x喜欢_mm256_set1_epi64x.它是什么意思?供参考,_mm256_set1_epi32没有这个后缀. 解决方案 tl:dr: mmx-> sse2 conversion Intinsics取得了non-x _mm_set/set1_epi64名称. 这是基于当前功能名称,已知历史记录和某些编译器行为的所有猜测工作: 第一个Intel Simd内在源是MMX. __m64是SSE2 __m128i和AVX2 __m256i的MMX等效物.当时没有64位x86 cpus,因此最宽的set内在__m64 _mm_set_pi32 (int e1, int e0).根据内在 - 芬德的说法,引入SSE2时,几年来不会得到英特尔的支持. (当时他们希望 ia-64/itanium x86).我没有检查过旧手册,但我想那是 __m128i _mm_set1_epi64 (__m64 a)当时可用, __m128i _mm_set1_
24 2024-04-22
编程技术问答社区
使用C# Vector<T> SIMD来查找匹配元素的索引
使用c#'s Vector,我们如何才能最有效地将查找索引的操作矢量化 的特定元素? 作为约束,集合将始终是整数原始的Span,并且最多包含1个匹配元素. 我提出了一个似乎还不错的解决方案,但是我很好奇我们是否能做得更好.这是方法: 创建A Vector仅由目标元素组成,在每个插槽中. 使用Vector.Equals()在上一个步骤中的输入集向量和向量之间,以获取一个掩码在单个匹配的插槽中包含1个(或者如果没有匹配,则仅0). 使用包含1个基的索引(1、2、3、4,...)的预启动矢量,从上一步和掩码之间调用Vector.Dot().每个索引将乘以0,除了潜在的匹配索引(将乘以1).我们返回的是这些乘法的总和,即0,或匹配元素的1基索引. 如果结果为0,则返回-1,无匹配.否则,从结果中减去一个基于0的基于0,然后返回. // One-time initialized vector containing { 1, 2, 3, 4
8 2024-04-19
编程技术问答社区
JitIntrinsicAttribute是如何影响代码生成的?
i正在浏览.NET源代码,并且看到此属性.它说, 可以连接到JIT固有方法/属性的属性 ,根据 msdn : 表明修改方法是一个内在值 Just-Ond-Ond(JIT)编译器可以执行特殊代码生成.这 班级不能继承. 但是我很难找到如何.它在哪种代码上执行特殊代码生成? 我的主要猜测是它主要使用诸如simd之类的处理器指令,例如 Java Jit做.这是.我对它的加速度感到好奇,我想知道Mono是否也这样做. 解决方案 这是 ryujit ,Microsoft当前正在处理的下一代64位抖动.仍在Alpha(又名CTP)中,下一个版本的.NET和Visual Studio计划包括它.当前在.NET 4.6预览中可用. Ryujit中的一个新功能是它可以利用Intel/AMD处理器中的矢量化指令来生成SIMD计算机代码的能力.使阵列上的浮点操作速度更快x8倍. [jitintrisic]属性是ryujit具有特殊内置知识的C#代码的标记,它将生成机
12 2024-04-15
编程技术问答社区
C#中的[Intrinsic]属性是做什么的?
快速的Google搜索" Instrinsic属性C#"仅返回有关其他属性的文章,例如[Serializable].显然,这些称为"内在属性". 但是,c#中也有一个属性,它本身称为[Intrinsic],我试图弄清楚它到底是什么以及它的工作原理.它不存在于 .NET文档的页面或文档中其他任何地方的页面. 此属性在.NET核心内部的多个位置都使用,例如,在 System.Numerics.Vectors 文件夹,例如 Vector2_Intrinsics.cs .代码片段: [Intrinsic] public Vector2(float x, float y) { X = x; Y = y; } 解决方案 这是我在通过 dotnet/corefx github上的存储库. [Intrinsic]标记可以被JIT替换/优化的方法,属性和字段.源代码注释说类似的话( IntrinsicAttribute.cs ): 呼叫对用此属性标记的字
4 2024-04-13
编程技术问答社区
如何将单精度浮点数的XMM寄存器转换为整数?
我在XMM寄存器内有一堆包装的浮子(使用SSE Internics): __m128 xmm = _mm_set_ps(4.0f, 3.0f, 2.0f, 1.0f); 我想一次将所有这些转换为整数.我找到了一个内在的,它可以执行我想要的(_mm_cvtps_pi16()),但是它产生了4x16位短而不是成熟的 int .一种称为_mm_cvtps_pi32()的固有性得出 int ,但仅适用于xmm中的两个较低值.我可以使用它,提取值,移动物品并再次使用它,但是有一种简单的方法吗?为什么不直接有32位填充的浮点 - > 32位整数指令?当然都适合XMM寄存器的同一空间? 编辑:好吧,我现在看到_mm_cvtps_pi32()返回__m64而不是__M128,这意味着它在MMX式MM ...寄存器上运行.这可以解释为什么它仅返回两个int,但现在我想知道: 编译X64时会遇到麻烦吗?据报道,那里不支持__ -M64 ... SSE推出时为什么不扩展此指令?
4 2024-04-09
编程技术问答社区
在ARM中把矢量寄存器作为float32x4_t的C变量来操作
我正在用手臂进行内联装配进行科学应用. 在我的汇编代码中,我必须(见最后的注释)名义上指出我要使用的向量寄存器.例如,在我的代码中,我有asm volatile("fadd v12.4S, v12.4S, v7.4S")在向量寄存器7和12之间进行向量浮点添加,将结果存储在矢量寄存器12中,以及其他内联汇编指令. 在"关键"装配代码部分之后,我想检索所述结果变量,并作为ARM NEON变量在C中进行操作.在我的情况下,向量将具有4x 32位变量,因此它们将是类型的float32x4_t. 到目前为止,我可以做类似的事情: float32_t my_var[4]; asm volatile("st1 {v12.4S}, [%[addr]]\n\t" : : [addr]"r"(my_var) : "x0", "x1"); /*from here on I can operate on my_var[0], my_var[1], etc without having to
12 2024-04-09
编程技术问答社区
在Altivec中是否可以旋转一个128位的值?
我正在试图将一些霓虹灯代码移植到Altivec.我们的霓虹灯代码有两个负载,一个腐烂,一个XOR和一家商店,因此似乎是一个简单的测试用例.根据IBM的 vec_rl 文档: 通过旋转由b. 除非-qarch=power8,vector unsigned int vector unsigned int 继续说vector unsigned int,在这种情况下vector unsigned long long适用. 我想执行128位旋转,而不是单个元素的32位或64位旋转.位位置是19、31、67、97和109.它们没有对齐. (常数来自 4x32和2x64是最大的Altivec数据安排?是否可以在Altivec中旋转128位值? 如果包装的旋转是唯一可用的操作,那么在C或Altivec中进行twiDdding是最好的做法? 解决方案 您可以使用vsld(vec_sld)进行8位旋转的旋转> + vsel(vec_sll + vec_srl + vec_sel
20 2024-04-09
编程技术问答社区
fC-我怎样才能在函数之外定义SIMD变量?
const __m128i ___n = _mm_set_epi32( 0x80808080, 0x80808080, 0x80808080, 0x80808080 ); const __m128i w___ = _mm_set_epi32( 0x80808080, 0x80808080, 0x80808080, 0x0f0e0d0c ); const __m128i z___ = _mm_set_epi32( 0x80808080, 0x80808080, 0x80808080, 0x0b0a0908 ); const __m128i zw__ = _mm_set_epi32( 0x80808080, 0x80808080, 0x0f0e0d0c, 0x0b0a0908 ); const __m128i y___ = _mm_set_epi32( 0x80808080, 0x80808080, 0x80808080, 0x07060504 );
12 2024-04-09
编程技术问答社区
_m_empty和_mm_empty之间有什么区别?
当我正在寻找MMX函数时,我注意到其中两个,_m_empty和_mm_empty,完全相同的定义. 那么为什么它们都存在呢?其中一个比另一个大吗?手册中是否没有提及? 解决方案 应该/应在文档中指出差异. msdn 更精确.他们明确提到了这一点: _mm _empty is _m_empty .
42 2024-04-09
编程技术问答社区
内在的__lzcnt64在不同的编译选项下返回不同的值
我有以下代码: #include #include #include long long lzcnt(long long l) { return __lzcnt64(l); } int main(int argc, char** argv) { printf("%lld\n", lzcnt(atoll(argv[1]))); return 0; } 使用不同的编译器和选项运行(汇编显示): clang $ clang -Wall src/test.c -D__LZCNT__ && ./a.out 2047 53 0000000000400560 : 400560: 55 push %rbp 400561: 48 89 e5 mov %rsp,%rbp 400564:
8 2024-04-09
编程技术问答社区
是否有一个x86的内在因素可以生成AVX512广播操作,从内存中的32位浮点值到512位寄存器?
指令存在(vbroadcastss zmm/m32),但似乎没有固有的生成. 我可以将其编码为 static inline __m512 mybroadcast(float *x) { __m512 v; asm inline ( "vbroadcastss %1,%0 " : "=v" (v) : "m" (*x) ); return v; } 有没有内联ASM的方法? 解决方案 我认为_mm512_set1_ps是您想要的. /landingpage/intinsicsGuide/#text = _mm512_set1_ps&Expand = 5236,4980
4 2024-04-09
编程技术问答社区
手臂霓虹灯内在转换D(64位)登记册为Q(128位)寄存器的一半,使上半部未定义
我希望能够能够在没有开销的情况下将uint8x8_t打入uint8x16_t> uint8x8_t,而上层64位则不确定.如果您只关心底部的64位,这很有用,但希望使用128位说明,例如: uint8x16_t data = (uint8x16_t)vld1_u8(src); // if you can somehow do this uint8x16_t shifted = vextq_u8(oldData, data, 2); 从我对ARM组装的理解中,应该可以通过将负载发送到D寄存器,然后解释为Q寄存器. . 我想到的一些方法是: data = vcombine_u8(vld1_u8(src), vdup_n_u8(0)); - 编译器似乎正在努力将上半部设置为0,即使这从来不是必需的 data = vld1q_u8(src); - 进行128位负载有效(在我的情况下很好),但在使用64位霓虹灯单位的处理器上可能会慢? 我想CPU中可能有一个部分依赖关
20 2024-04-09
编程技术问答社区