问题标签 [sse4]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - 如何并行比较两个以上的数字?
是否可以使用 SSE4 在一条指令中比较多个数字?
英特尔参考说以下关于 PCMPGTQ
PCMPGTQ - 比较打包数据是否大于
对目标操作数(第一个操作数)和源操作数(第二个操作数)中的压缩四字执行 SIMD 比较。如果第一个(目标)操作数中的数据元素大于第二个(源)操作数中的对应元素,则将目标中对应的数据元素设置为全1;否则,设置为 0。
这并不是我真正想要的,因为我希望能够确定向量中哪些整数更大,哪些更小。
例如,如果我需要比较
我打算放入[32, 13, 44, 99]
一个向量和[45, 78, 12, 66]
另一个向量,并在一条指令中使用 SSE4 比较它们,并得到[0, 0, 1, 1]
结果(0 - 更少,1 - 更大)
但这似乎不是 PCMPGTQ 所做的。有关如何在此级别使用并行性来加速此比较的任何建议?
c - 如何在我的计算机上启用对 POPCNT 指令/内在函数的支持?
我试图在我的电脑(Fedora 17 32bit)上运行以下程序。如何使我的系统支持popcnt
快速人口计数指令?
我编译了程序并运行它,但得到以下异常:
以下是我的处理器的信息:
c++ - pcmpestri instruction to write similar strpos function?
How can the pcmpestri
instruction be used to write a function similar to strpos
function in C++? I can use g++ compiler.
pcmpestri
is a new instruction that is found in SSE4
c - _mm_crc32_u64 定义不明确
为什么在世界上被_mm_crc32_u64(...)
这样定义?
“crc32”指令总是累积 32 位 CRC,而不是64 位 CRC(毕竟,CRC32 不是 CRC64)。如果机器指令 CRC32恰好有一个 64 位目标操作数,则高 32 位将被忽略,并在完成时用 0 填充,因此永远没有 64 位目标。我理解为什么英特尔允许在指令上使用 64 位目标操作数(为了统一),但如果我想快速处理数据,我想要一个尽可能大的源操作数(即,如果我有那么多数据,则为 64 位,尾端更小)并且始终是 32 位目标操作数。但是内在函数不允许 64 位源和 32 位目标。注意其他内在函数:
"crc" 的类型不是 8 位类型,返回类型也不是,它们是 32 位。为什么没有
? 英特尔指令支持这一点,这是最有意义的内在。
有没有人有可移植的代码(Visual Studio 和 GCC)来实现后者?谢谢。 我的猜测是这样的:
对于 GCC,以及
对于 VisualStudio。不幸的是,我对约束的工作原理知之甚少,对汇编级编程的语法和语义也没有什么经验。
小编辑:注意我定义的宏:
注意最后一个宏语句有多么不同。缺乏统一性当然表明内在的定义没有得到合理的定义。虽然没有必要(uint64)
在最后一个宏中进行显式转换,但它是隐式的并且确实会发生。反汇编生成的代码显示了 32->64 和 64->32 的代码,这两者都是不必要的。
换句话说,它是_mm_crc32_u64
,不是 _mm_crc64_u64
,但他们已经实现了它,就好像它是后者一样。
如果我能得到CRC32
正确的上述定义,那么我想将我的宏更改为
c++ - 使用 sse 的快速紧凑型寄存器
我试图弄清楚如何使用 sse _mm_shuffle_epi8 来压缩 128 位寄存器。
假设我有一个输入变量
基本上是8个16位,表示为:
我的输出称为:
现在我有一个大小为 8 的位向量:
好的,如何根据bit_mask和输入目标得到最终结果?
假设我的位向量是:
那么我希望结果是:
使用 _mm_shuffle_epi8 的任何已知方法?
假设我使用查找数组: _mm_shuffle_epi8(a, mask_lookup[bitvector]);
如何创建数组?
x86 - 在没有 AVX(2) 的情况下进行 SIMD 收集的最快方法是什么?
假设我有 SSE 到 SSE4.1,但没有 AVX(2),那么加载这样的压缩内存布局的最快方法是什么(所有 32 位整数):
分成四个向量a, b, c, d
?
我不确定这是否相关,但在我的实际应用程序中,我有 16 个向量,因此a0
在a1
内存中相隔 16*4 字节。
c++ - SSE42 & STTNI - PcmpEstrM 比 PcmpIstrM 慢两倍,是真的吗?
我正在尝试使用 SSE42 和 STTNI 指令并且得到了奇怪的结果 - PcmpEstrM(使用显式长度字符串)运行速度比 PcmpIstrM(隐式长度字符串)慢两倍。
- 在我的i7 3610QM上,差异是2366.2 ms 与 1202.3 ms - 97%。
- 在i5 3470上差异不是很大,但仍然很重要 = 3206.2 ms 与 2623.2 ms - 22%。
两者都是“常春藤桥” - 奇怪的是它们有如此不同的“差异”(至少我在他们的规格中看不到任何技术差异 - http://www.cpu-world.com/Compare_CPUs/Intel_AW8063801013511,Intel_CM8063701093302 /)。
Intel 64 和 IA-32 架构优化参考手册提到 PcmpEstrM 和 PcmpIstrM 的相同吞吐量 = 11 和延迟 = 3。因此,我希望两者的表现相似。
问:是我实际设计/预期的差异还是我以错误的方式使用这些指令?
下面是我的虚拟测试场景(VS 2012)。逻辑非常简单 - 扫描 16MB оf 文本以查找匹配字符。由于 haystack 和 needle string 都不包含零终止符 - 我希望 E 和 I 具有相似的性能。
PS:我尝试在英特尔的开发论坛上发布此问题,但他们将其识别为垃圾邮件:(
linux - MOVDQU 指令 + 页边界
我有一个简单的测试程序,它使用 movdqu 指令加载一个 xmm 寄存器,该指令在页面边界(OS = Linux)上访问数据。
如果映射了以下页面,则可以正常工作。如果它没有被映射,那么我会得到一个 SIGSEGV,这可能是预期的。
然而,这大大降低了未对齐负载的有用性。此外,允许未对齐内存引用的 SSE4.2 指令(如 pcmpistri)似乎也表现出这种行为。
这一切都很好——除了我发现有许多使用 pcmpistri 的 strcmp 实现似乎根本没有解决这个问题——而且我已经能够设计出会导致这些实现失败的琐碎测试用例,而一次一个字节的琐碎 strcmp 实现将在相同的数据布局下正常工作。
还有一点需要注意——64 位 Linux 的 GNU C 库实现似乎有一个 __strcmp_sse42 变体,它似乎以更安全的方式使用 pcmpistri 指令。这个 strcmp 的实现相当复杂,但它似乎在小心翼翼地试图避免页面边界问题。我不确定这是由于我上面描述的问题,还是只是试图通过对齐数据来获得更好的性能的副作用。
无论如何,我的问题主要是——我在哪里可以找到更多关于这个问题的信息?我已经输入了“movdqu 跨越页面边界”以及我能想到的谷歌的每一个变体,但没有遇到任何特别有用的东西。如果有人可以向我指出有关这方面的更多信息,将不胜感激。
alignment - 带有 -xSSE4.1 标志的分段错误
运行使用 -xSSE4.1 编译标志构建的可执行文件时出现分段错误。我在支持 SSE4.1、SSE4.2 和 AVX 的机器上运行它。
导致分段错误的内在函数:
结构定义:
TOT_NUM_PARTS 是一个值为 17 的枚举,而 WORD16 是一个短整数。
gdb 中的“layout asm”命令显示了被转换为的内在代码段:
第 7 行:
0x5cc008 <hme_calc_sad_and_result_num_part_lt_9+136> movdqa 0x22(%r10),%xmm7
给我一个分段错误。
$r10 的值0x7fffd4f22fe0
就在执行第 6 行之前;这是一个 16 字节对齐的地址,因此第 6 行执行没有问题。但是第 7 行是从地址加载的,(0x7fffd4f22fe0 + 0x22)
该地址不是 16 字节对齐的。gdb 也打印&ps_mv_refine_ctxt->i2_tot_cost[0][0]
as 0x7fffd4f22fe0
which is $r10 的值。
我担心的是为什么前两个在应该是 movdqu 的时候被_mm_loadu_si128
翻译成movdqa。
当我使用 -xSSE4.2 或 -xAVX 编译标志构建相同的可执行文件时,所有四个 _mm_loadu_si128 指令都被转换为movdqu,因此没有问题。此外,该问题仅在 release-build (-O3 标志)中可见。
我正在使用英特尔 C/C++ 编译器。我觉得__declspec(align(16))
结构定义中没有必要。但它不会导致这种奇怪的行为(通过删除它进行测试,发现行为没有变化)。
对不起,很长的帖子。认为这些细节是必要的。
c++ - _mm_load_ps 是 128 位对齐结构的要求吗?
我有一个与此类似的向量结构设置:它是 128 位对齐的,就像 __m128 类型一样。
我正在使用 SSE 4.1 点积指令 _mm_dp_ps。是否需要为我的以上结构使用 _mm_load_ps 已经对齐 128 位,或者我可以直接转换我的结构吗?这是安全的做法吗?
注意:使用 VS2013 并包含。
使用 _mm_load_ps 的当前代码:
问题代码:
编辑:做了一些测试
使用这个简单的控制台应用程序代码,我运行了 3 个不同的测试。第一次使用 _mm_load_ps,第二次将结构转换为 __m128 类型,最后使用联合内部的 __m128 类型。
结果是: end_a : 26489 滴答 end_b : 19375 滴答 end_c : 18767 滴答
我也单步执行了代码,从 res_a 到 res_c 的所有结果都是正确的。所以这个测试表明使用联合更快。
我知道默认情况下 __m128 类型是对使用的寄存器的引用,而不是类型,但是当包含 smmintrin.h 时,__m128 成为 xmmintrin.h 中定义为的联合
所以我相信使用内在包含执行的指令不是引用寄存器,而是引用 xmmintrin.h 中定义的 __m128 类型。
因此,为了在此测试后更好地重复我的问题:在结构内部使用 xmmintrin.h 中定义的 __m128 结构与 Visual Studio 2013 可用的内在函数一起使用是否安全?