内在示例 - 这里发生了啥(包括完整的代码)?

Posted

技术标签:

【中文标题】内在示例 - 这里发生了啥(包括完整的代码)?【英文标题】:Intrinsics example- what is happening here (complete code included)?内在示例 - 这里发生了什么(包括完整的代码)? 【发布时间】:2013-10-19 15:37:48 【问题描述】:

我从以下代码中找到了以下代码:

http://msdn.microsoft.com/en-us/library/bb513993(v=vs.90).aspx

我试图准确地了解代码在做什么,然后修补并满足我的需要。我有兴趣使用 intrincs 在字符串中快速查找空格字符,我认为这些字符串内部函数可以帮助我。

我不太明白printf语句中提供的“注释”,为什么预期的结果是作者所说的?

(你应该可以复制并粘贴下面的内容并立即运行)

#include <stdio.h>
#include <nmmintrin.h>
#include <iostream>

using namespace std;

int main ()

    __m128i a, b;


    const int mode = _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_LEAST_SIGNIFICANT;
    //      _SIDD_UWORD_OPS         a and b contain strings of unsigned 16-bit characters.  
    //      _SIDD_CMP_EQUAL_EACH    Find if equal each mode: This implements the string equality algorithm.
    //      _SIDD_LEAST_SIGNIFICANT sets the same bit as _SIDD_BIT_MASK


    a.m128i_u16[7] = 0xFFFF;
    a.m128i_u16[6] = 0xFFFF;
    a.m128i_u16[5] = 0xFFFF;
    a.m128i_u16[4] = 0xFFFF;
    a.m128i_u16[3] = 0xFFFF;
    a.m128i_u16[2] = 0xFFFF;
    a.m128i_u16[1] = 0xFFFF;
    a.m128i_u16[0] = 0xFFFF;

    b.m128i_u16[7] = 0x0001;
    b.m128i_u16[6] = 0x0001;
    b.m128i_u16[5] = 0x0001;
    b.m128i_u16[4] = 0x0001;
    b.m128i_u16[3] = 0x0001;
    b.m128i_u16[2] = 0x0001;
    b.m128i_u16[1] = 0x0001;
    b.m128i_u16[0] = 0x0001;

    int returnValue = _mm_cmpistra(a, b, mode);
    printf_s("_mm_cmpistra return value should be 1: %i\n", returnValue);

    b.m128i_u16[4] = 0x0000;
    returnValue = _mm_cmpistra(a, b, mode);
    printf_s("_mm_cmpistra return value should be 0: %i\n", returnValue);

    b.m128i_u16[5] = 0xFFFF;
    returnValue = _mm_cmpistrc(a, b, mode);
    printf_s("_mm_cmpistrc return value should be 0: %i\n", returnValue);

    b.m128i_u16[4] = 0x0001;
    returnValue = _mm_cmpistrc(a, b, mode);
    printf_s("_mm_cmpistrc return value should be 1: %i\n", returnValue);

    returnValue = _mm_cmpistri(a, b, mode);
    printf_s("_mm_cmpistri return value should be 5: %i\n", returnValue);

    b.m128i_u16[0] = 0xFFFF;
    __m128i fullResult = _mm_cmpistrm(a, b, mode);
    printf_s("_mm_cmpistrm return value: 0x%016I64x 0x%016I64x\n",
                fullResult.m128i_u64[1], fullResult.m128i_u64[0]);

    returnValue = _mm_cmpistro(a, b, mode);
    printf_s("_mm_cmpistro return value should be 1: %i\n", returnValue);

    returnValue = _mm_cmpistrs(a, b, mode);
    printf_s("_mm_cmpistrs return value should be 0: %i\n", returnValue);

    a.m128i_u16[7] = 0x0000;
    returnValue = _mm_cmpistrs(a, b, mode);
    printf_s("_mm_cmpistrs return value should be 1: %i\n", returnValue);

    returnValue = _mm_cmpistrz(a, b, mode);
    printf_s("_mm_cmpistrz return value should be 0: %i\n", returnValue);

    b.m128i_u16[7] = 0x0000;
    returnValue = _mm_cmpistrz(a, b, mode);
    printf_s("_mm_cmpistrz return value should be 1: %i\n", returnValue);

    int bb;
    cin >> bb;

    return 0;

【问题讨论】:

有些 SSE 大师会停下来告诉你所有这些内在函数的作用并非不可能,但实际上,这似乎只是“在手册中查找”的情况(除了您在问题中链接的 MSDN 参考,您可能还应该下载英特尔 SSE4 参考的副本)。 我有手册(和内在指南小程序)——问题是他们并没有真正“解释”它——只是复制和粘贴的简短解释。英特尔手册是极简主义的,实际上并没有比我提供的 msdn 链接更多。 Page 50 and 100 onwards here (SSE4 instructions reference) 和 this 和 MSDN 参考似乎是你所需要的。 【参考方案1】:

你现在要么疯了,要么想通了。但... 以“i”结尾的内在函数返回某个出现的索引。 以“m”结尾的内在函数返回一个掩码(位/字节/字取决于...) 以“c”、“o”、“s”或“z”结尾的内在函数返回单个 EFLAGS 位。 以“a”结尾的内在函数返回 CFlag AND ZFlag 的布尔结果。 (不是 AFlag。)这样做是为了有一种简单的方法来测试您正在寻找的事件的发生以及使用单个指令的输入之一的结束。 在思考如何在高级语言中使用这些指令方面,我确实做得很糟糕。当时我完全满足于进入内联 ASM 以访问这些指令。它们真的有点……复杂……在更高级别的语言中有效使用,比如 C。对不起。如果你真的加入 ASM,它们会很有趣。使用 3 或 4 个指令循环可以完成多少工作,这有点酷。

【讨论】:

以上是关于内在示例 - 这里发生了啥(包括完整的代码)?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 这里到底发生了啥? [关闭]

对于每个未发送到后续函数的循环值。这里发生了啥?节点.js

这个函数顶部发生了啥

需要确切知道这段代码中发生了啥

这里发生了啥?核心数据/iCloud

有人可以解释一下这里发生了啥吗?存在普遍量化