使用英特尔编译器内在函数,给定一个128位寄存器,打包8个16位元素,如何从寄存器中访问(廉价)任意元素,以便后续使用_mm_cvtepi8_epi64(符号扩展两个8位元素,打包在较低位置) 16位寄存器,两个64位元素)?
我会解释为什么我问:
0x0和包装两个四字(64位)0xffff ffff ffff ffff.注意:输入缓冲区的值0x0和值0xff可以更改为最有用的值,前提是在总和之前屏蔽效果仍然存在.
从我的问题可以明显看出,我目前的计划如下,在输入缓冲区中流式传输:
谢谢,阿萨夫
假设有一个__m128变量包含4个SP值,并且您想要最小值,是否有任何可用的内部函数,或者除了值之间的天真线性比较之外的任何其他函数?
正确知道我的解决方案如下(假设输入__m128变量是x):
x = _mm_min_ps(x, (__m128)_mm_srli_si128((__m128i)x, 4));
min = _mm_min_ss(x, (__m128)_mm_srli_si128((__m128i)x, 8))[0];
Run Code Online (Sandbox Code Playgroud)
这是非常可怕的,但它的工作(顺便说一下,有什么类似的_mm_srli_si128但是__m128类型?)
我有以下C代码:
__m128 pSrc1 = _mm_set1_ps(4.0f);
__m128 pDest;
int i;
for (i=0;i<100;i++) {
m1 = _mm_mul_ps(pSrc1, pSrc1);
m2 = _mm_mul_ps(pSrc1, pSrc1);
m3 = _mm_add_ps(m1, m2);
pDest = _mm_add_ps(m3, m3);
}
float *arrq = (float*) pDest;
Run Code Online (Sandbox Code Playgroud)
直到for循环结束的所有内容都有效.我现在要做的是将__m128类型转换回float.因为它存储了4个浮点数,我认为我很容易将其转换为浮动*.我究竟做错了什么?(这是一个测试代码,所以不要怀疑).我基本上尝试了所有可能的转换.谢谢你的帮助.
如何使用 512 位 AVX 寄存器中的浮点数有效地执行水平加法(即将单个向量中的项加在一起)?对于 128 和 256 位寄存器,这可以使用 _mm_hadd_ps 和 _mm256_hadd_ps 来完成,但没有 _mm512_hadd_ps。Intel 内在函数指南文档 _mm512_reduce_add_ps。它实际上并不对应于单个指令,但它的存在表明存在一种最佳方法,但它似乎没有在 GCC 最新快照附带的头文件中定义,我找不到它与谷歌。
我认为可以使用 _mm512_shuffle_ps 和 _mm512_add_ps 模拟“hadd”,或者我可以使用 _mm512_extractf32x4_ps 将 512 位寄存器分解为四个 128 位寄存器,但我想确保我不会错过更好的东西。
我试图改变这个代码来处理std::vector<int>.
float accumulate(const std::vector<float>& v)
{
// copy the length of v and a pointer to the data onto the local stack
const size_t N = v.size();
const float* p = (N > 0) ? &v.front() : NULL;
__m128 mmSum = _mm_setzero_ps();
size_t i = 0;
// unrolled loop that adds up 4 elements at a time
for(; i < ROUND_DOWN(N, 4); i+=4)
{
mmSum = _mm_add_ps(mmSum, _mm_loadu_ps(p + i));
}
// add up single values until all …Run Code Online (Sandbox Code Playgroud) 如何将128位xmm寄存器拆分为两个64位quadwords?
我输入的字数非常多xmm1,想要将较高的四字r9和较低的四字输入r10,或RAX和RDX。
movlpd或movhpd仅与reg到mem兼容,反之亦然。
有没有办法获得存储在__m256d变量中的值的总和?我有这个代码.
acc = _mm256_add_pd(acc, _mm256_mul_pd(row, vec));
//acc in this point contains {2.0, 8.0, 18.0, 32.0}
acc = _mm256_hadd_pd(acc, acc);
result[i] = ((double*)&acc)[0] + ((double*)&acc)[2];
Run Code Online (Sandbox Code Playgroud)
此代码有效,但我想用SSE/AVX指令替换它.
我已经实现了一种使用 .NET 中可用的 SIMD 内在函数解析长度 <= 8 的无符号整数字符串的方法,如下所示:
public unsafe static uint ParseUint(string text)
{
fixed (char* c = text)
{
var parsed = Sse3.LoadDquVector128((byte*) c);
var shift = (8 - text.Length) * 2;
var shifted = Sse2.ShiftLeftLogical128BitLane(parsed,
(byte) (shift));
Vector128<byte> digit0 = Vector128.Create((byte) '0');
var reduced = Sse2.SubtractSaturate(shifted, digit0);
var shortMult = Vector128.Create(10, 1, 10, 1, 10, 1, 10, 1);
var collapsed2 = Sse2.MultiplyAddAdjacent(reduced.As<byte, short>(), shortMult);
var repack = Sse41.PackUnsignedSaturate(collapsed2, collapsed2);
var intMult = Vector128.Create((short)0, 0, 0, 0, 100, …Run Code Online (Sandbox Code Playgroud) 我必须对相对较小的整数进行大量操作(加法),并且我开始考虑哪种数据类型在 64 位机器上能提供最佳性能。
\n我确信uint16将 4 加在一起所需的时间与 1 相同uint64,因为 ALU 可以uint16仅使用 1 个uint64加法器进行 4 次加法。(进位传播意味着这对于单个 64 位加法器来说并不容易,但这就是整数 SIMD 指令的工作原理。)
显然情况并非如此:
\nIn [3]: data = np.random.rand(10000)\n\nIn [4]: int16 = data.astype(np.uint16)\n\nIn [5]: int64 = data.astype(np.uint64)\n\nIn [6]: int32 = data.astype(np.uint32)\n\nIn [7]: float32 = data.astype(np.float32)\n\nIn [8]: float64 = data.astype(np.float64)\n\nIn [9]: %timeit int16.sum()\n13.4 \xc2\xb5s \xc2\xb1 43.3 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000 loops each)\n\nIn [10]: %timeit int32.sum()\n13.9 \xc2\xb5s \xc2\xb1 347 …Run Code Online (Sandbox Code Playgroud) 使用VBROADCASTS命令在AVX中很容易,如果值是double或float,则在SSE中很容易.
如何向Delphi ASM中的XMM寄存器中的每个插槽广播一个8位值?