c - SSE等 vector 编程(SIMD)

标签 c x86 sse simd

我对 SSE 编程完全陌生,但我有一个 Intel Core i7 处理器。

基本上,我想一次取 4 个 32 位无符号整数并将它们全部立方(升至 3 次方)。据我了解,SSE 及其后继产品的 SIMD 功能使这成为可能,但我到底该怎么做呢?最好使用 C 语言,但如有必要,我可以管理汇编。

编辑以明确我的最终目标:

然后,我想将所有立方体加在一起得到一个数字。

背景:我只是想使用 SSE 来优化确定一个数字是否为阿姆斯特朗数(一个三位数,其每个数字的立方之和与数字本身相同)。一个例子是 153。除了蛮力之外似乎没有办法做到这一点。这些是自恋数字的子集,其所有数字的总和为十进制数的幂次方等于数字本身。希望我最终能将它扩展为更加灵活,开始时我只是在做阿姆斯壮的数字。正如您可能想象的那样,它出现在另一个网站上,我们中的一些人正试图从中优化它。根据您的想法和我自己的研究,我想出了这个代码:

#include <stdio.h>
#include <smmintrin.h>  // SSE 4.1

__m128i vcube(const __m128i v)
{
    return _mm_mullo_epi32(v, _mm_mullo_epi32(v, v));
}


int main(int argc, const char * argv[]) {
    for (unsigned int i = 1; i <= 500; i++) {
        unsigned int firstDigit = i / 100;
        unsigned int secondDigit = (i - firstDigit * 100) / 10;
        unsigned int thirdDigit = (i - firstDigit * 100 - secondDigit * 10);

        __m128i v = _mm_setr_epi32(0, firstDigit, secondDigit, thirdDigit);
        __m128 v3 = (__m128) vcube(v);

        v3 = _mm_hadd_ps(v3, v3);
        v3 = _mm_hadd_ps(v3, v3);

        if (_mm_extract_epi32((__m128i) v3, 0) == i)    
            printf ("%03d is an Armstrong number\n", i);
        }
    return 0;
}

注意:我必须进行一些类型转换才能使其在某些系统(Solaris,至少是某些 Linux)中编译。

所以这可行,但也许可以简化。抱歉,我没有发布整个任务,但我试图将其分解为多个步骤,并且我想确保每个数字的立方都正确。

(结束编辑)

谢谢!

编辑:我想我应该补充一下我正在运行 Mac OS X Sierra。

再次编辑:

那么,假设我制作了所有这些无符号短裤而不是无符号整数并添加更多数字,当短裤可能无法保存所有数字的总和时如何将它们加在一起?如果您明白我的意思,有没有一种方法可以将它们相加并存储在更大变量的 vector 中,或者像 UInt64 这样的普通更大的数字?

很抱歉提出所有问题,但正如我所说,我对 vector 处理完全陌生,尽管我从第一台 Mac G4 开始就接触过它。

最佳答案

如果您的输入值在 0..1625 范围内(这样结果适合 32 位),那么您可以使用 _mm_mullo_epi32 :

__m128i vcube(const __m128i v)
{
    return _mm_mullo_epi32(v, _mm_mullo_epi32(v, v));
}

演示:

#include <stdio.h>
#include <smmintrin.h>  // SSE 4.1

__m128i vcube(const __m128i v)
{
    return _mm_mullo_epi32(v, _mm_mullo_epi32(v, v));
}

int main()
{
    __m128i v = _mm_setr_epi32(0, 1, 1000, 1625);
    __m128i v3 = vcube(v);

    printf("%vlu => %vlu\n", v, v3);

    return 0;
}

编译和测试:

$ gcc -Wall -Wno-format-invalid-specifier -Wno-format-extra-args -msse4 vcube.c && ./a.out
0 1 1000 1625 => 0 1 1000000000 4291015625

关于c - SSE等 vector 编程(SIMD),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44514385/

相关文章:

assembly - x86 程序集 16 位相对调用

c++ - 我对缓存性能的推理是否正确?

c - 如何使用 GNU C vector 扩展从 double 组加载/存储到 double 组?

algorithm - 查找 SSE 寄存器中出现频率最高的元素

c - 使用随机值开始循环,然后循环整个范围

客户端使用C使用TCP套接字将数据发送到端口

python - 优化sympy生成的代码

c - POSIX C 中的打开功能不起作用

c - 从 128 位 SSE vector 加载和提取 32 位整数值的最有效方法是什么?

performance - 从一个数组中减去另一个数组的最高效方法