如何使用SSE装配说明找到毕达哥拉斯三元组?

时间:2016-12-19 22:26:46

标签: c assembly sse

我在组装方面非常新,我想找到1到100范围内的所有毕达哥拉斯三元组。我在C中生成所有数字,所有其他计算应该在汇编SSE中完成。我试图通过使用sqrt命令来做到这一点(我已经尝试了所有这些)但我无法使它工作.. 有人能告诉我应该怎么做吗?

到目前为止我所得到的:

int main(){
            for (int i = 1; i <= 100; i++)
            {
                a++;
                if (a > 100)
                    a = 0;
                for (int j = 1; j <= 100; j++)
                {
                    b++;
                    if (b > 100)
                        b = a;
                    _asm   //tricky part begins here:
                    {
                        movups xmm0, a
                        movups xmm1, b
                        pmuludq xmm0, xmm0  
                        pmuludq xmm1, xmm1 
                        //movups xmm2, 0  
                        //paddd xmm2, xmm0  
                        //paddd xmm2, xmm1
                        movups z, xmm0
                    }
                    printf("%d\n", z);
                }
          }
    }

1 个答案:

答案 0 :(得分:2)

您的方法的基本问题是您需要并行查看4个b值,因此您无法从C标量变量加载。你需要在循环迭代中将东西保存在向量寄存器中,因为你不是只是从内存或其他东西加载向量。您应该在asm中编写整个循环,因为MSVC内联asm很容易包装短序列,因为结果输入/输出不可避免的开销。

当然,对这个循环进行矢量化的最好方法是使用C内在函数,而不是使用内联asm。然后,如果需要(并且如果可能的话),您可以通过检查其asm输出来实现低效率,从而将编译器手动保持为更好的asm。 (见Why is this C++ code faster than my hand-written assembly for testing the Collatz conjecture?

当然,如果你真的只想创建生成毕达哥拉斯三元组的高效代码,那么你的算法也是假的:

维基百科文章有一个generating a triple部分,描述了欧几里德的公式。迭代这将是一个不同的问题,而不是检查整个a=[1..100] b=[1..100]搜索空间的强力搜索中的命中,因为检查数字是否是一个完美的正方形是相当慢的。

另外,检测哪些向量元素与条件匹配是笨拙的。打包比较指令然后PMOVMSKB(或MOVMSKPS)会给你一个位图,但是当命中很少时,这种方法效果最好,例如:实现memchr,在第一次点击后你的循环停止。