Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何使用SSE计算mod/余数?_Assembly_Sse_Division - Fatal编程技术网

Assembly 如何使用SSE计算mod/余数?

Assembly 如何使用SSE计算mod/余数?,assembly,sse,division,Assembly,Sse,Division,在x64/sse上使用矢量指令计算x%M的最佳/最快方法是什么?(我所说的%是指模/余数) 我找不到压缩mod的任何操作码,所以我认为我能做的最好的方法是将int提升为float,然后使用DIVPS和ROUNDPS计算x-m*floor(x/m) 还是有一个更好的选择我错过了 更新:M仅在运行时已知,实际循环如下所示: unsigned x[SIZE], M[SIZE], answer[SIZE]; for (int i = 0; i < SIZE; i++) { answer[i]

在x64/sse上使用矢量指令计算x%M的最佳/最快方法是什么?(我所说的%是指模/余数)

我找不到压缩mod的任何操作码,所以我认为我能做的最好的方法是将int提升为float,然后使用DIVPS和ROUNDPS计算x-m*floor(x/m)

还是有一个更好的选择我错过了

更新:M仅在运行时已知,实际循环如下所示:

unsigned x[SIZE], M[SIZE], answer[SIZE];
for (int i = 0; i < SIZE; i++) {
  answer[i] = x[i] % M[i];
}
无符号x[SIZE],M[SIZE],应答[SIZE];
对于(int i=0;i

此外,已知M在1-640000000范围内,如果它有任何帮助的话

如果
M
是编译时常量或循环中的常量,则可以不使用除法。我们可以写作

x/M = (x*(2^n/M))>>n
系数
2^n/M
(aka)应在循环之前或编译时计算

例如,如果我们想要
x[i]/5
,并且我们知道
x[i]
小于
2^15
,我们可以使用
2^n/M=0xCCCD
n=18

#include <stdio.h>
#define N 32768
int x[N], y[N], z[N];

int main(void) {
    for(int i=0; i<N; i++) x[i] = i;
    int M = 5;
    int fact = 0xCCCD;
    int n = 18;
    for(int i=0; i<N; i++) {
        y[i] = x[i]/M;
        z[i] = (fact*x[i])>>n;
        if(y[i] != z[i]) printf("%d %d\n", y[i], z[i]);
    }
}
#包括
#定义N 32768
int x[N],y[N],z[N];
内部主(空){
对于(int i=0;in;
如果(y[i]!=z[i])printf(“%d%d\n”,y[i],z[i]);
}
}
有几种不同的方法来确定幻数和
n
。我使用。它可以为您使用SSE2或AVX2来确定32位数字(而不是上面代码中的15位数字)。如果您想看到汇编代码来确定幻数,his也可以为SSE2(可能还有AVX2)确定幻数


有关更多详细信息,请参阅VCL手册第22页。手册中也对其汇编库进行了描述。

没有比这快多少。此外,您可能需要检查是否存在一个舍入错误。如果分数部分非常接近
0.5
。除非M是2的幂,否则我认为你运气不好。
M
是编译时常数吗?好的,我现在明白了,M每次迭代都会改变
M[I]
。我的答案中的方法对你没有帮助。很抱歉,我忘了告诉你m只在运行时可用。我会更新这个问题。谢谢你的回答,我不知道Fog的VCL,它看起来非常有用。@Ricbit
m
不需要是编译时常量。它只需要在循环中保持常量。这需要时间计算
fact
n
。如果每次迭代都要这样做,那会比除法慢。但是如果你在循环之前计算它们,那么使用乘法和移位会快得多。事实证明,即使不使用sse,用两次乘法替换mod也确实有好处。再次感谢你的帮助想法。应该指出的是,对于16位数字,有
\u mm\u mulhi\u epu16
来获得每个产品的高半部(bit
[31:16]
)。这意味着您不必扩展到32位,事实上不应该,因为SSE4
pmulld
在Haswell和更高版本上更慢。