C++ 64位双精度点积向量比32位无符号整数向量快?
我有两种代码设计,迭代大小为500的向量。其中一种设计包含64位双精度数组,第二种设计使用包含32位整数的数组。我原以为32位设计会更快,因为缓存中可以打包更多有用的数据 编译器MSVC,CPU常春藤桥,编译64位模式 这是代码1,使用32位整数(在2600CPU周期内运行):C++ 64位双精度点积向量比32位无符号整数向量快?,c++,performance,optimization,cpu,compiler-optimization,C++,Performance,Optimization,Cpu,Compiler Optimization,我有两种代码设计,迭代大小为500的向量。其中一种设计包含64位双精度数组,第二种设计使用包含32位整数的数组。我原以为32位设计会更快,因为缓存中可以打包更多有用的数据 编译器MSVC,CPU常春藤桥,编译64位模式 这是代码1,使用32位整数(在2600CPU周期内运行): #包括 #包括 int main(){ std::向量x1; std::向量x2; std::矢量x3; x1.调整大小(500); x2.调整大小(500); x3.调整大小(500); 对于(int i=0;i不同之
#包括
#包括
int main(){
std::向量x1;
std::向量x2;
std::矢量x3;
x1.调整大小(500);
x2.调整大小(500);
x3.调整大小(500);
对于(int i=0;i不同之处在于第一个代码中整数到双精度的转换(向量包含无符号int
,乘积是整数算术,但累加使用双精度
,在汇编程序中,这将cvtsi2sd
指令添加到代码中)
在第二段代码中,到处都使用double,因此不需要进行转换,代码运行速度更快
如果CPU在固定和浮点处理单元之间有更严格的区别,那么这种差异会更加明显(POWER platform就是一个例子).X86平台在这方面非常宽容。它是一个64位CPU,对吗?浮点运算可以与其他CPU指令并行执行,因此这可能会导致差异。虽然反汇编显示两者都使用xmm寄存器,所以现在我也感到困惑。另一个论坛上有一些类似的问题。.据我所知,像APFLOAT这样的扩展精度数学例程使用浮点执行操作,但我不知道是否使用了SSE类型的指令。我将更改代码以包含完整的可编译示例。我认为是的,这就是你的情况……fp和整数类型之间的转换通常会减慢(有时很多)。。。
#include <vector>
#include <iostream>
int main(){
std::vector<unsigned int> x1;
std::vector<unsigned int> x2;
std::vector<unsigned int> x3;
x1.resize(500);
x2.resize(500);
x3.resize(500);
for(int i =0; i<500; i++){
x1[i] = i;
x2[i] = 2*i;
x3[i] = 4*i;
}
int counter = 0;
while(counter < 1000){
unsigned long long start = 0;
unsigned long long end = 0;
double m = 0;
double n = 0;
start = __rdtsc();
for(int i=0; i < 500; i++){
unsigned int a = x1[i];
unsigned int b = x2[i];
unsigned int g = x3[i];
m = m + (a * g);
n = n + (b * g);
}
end = __rdtscp();
std::cout << (end-start) << "\t\t"<<m << n << std::endl;
counter++;
}
}
start = __rdtscp(&p);
rdtscp
lea r8,[rbp+6Fh]
mov dword ptr [r8],ecx
shl rdx,20h
or rax,rdx
mov r10,rax
unsigned int p;
unsigned int q;
unsigned long long start = 0;
unsigned long long end = 0;
double m = 0;
mov r8,rbx
mov r9d,1F4h
unsigned int a = x1[i];
unsigned int b = x2[i];
unsigned int g = x3[i];
mov edx,dword ptr [r8+r15]
m = m + (a * g);
mov ecx,edx
imul ecx,dword ptr [r8+r14]
xorps xmm0,xmm0
cvtsi2sd xmm0,rcx
addsd xmm7,xmm0
n = n + (b * g);
imul edx,dword ptr [r8]
mov eax,edx
xorps xmm0,xmm0
cvtsi2sd xmm0,rax
addsd xmm8,xmm0
for(int i=0; i < 500; i++){
add r8,4
dec r9
jne main+0E5h (013F681261h)
}
end = __rdtscp(&q);
rdtscp
}
end = __rdtscp(&q);
lea r8,[rbp+6Fh]
mov dword ptr [r8],ecx
shl rdx,20h
or rdx,rax
#include <vector>
#include <iostream>
int main(){
std::vector<double> x1;
std::vector<double> x2;
std::vector<unsigned long long> x3;
x1.resize(500);
x2.resize(500);
x3.resize(500);
for(int i =0; i<500; i++){
x1[i] = i;
x2[i] = 2*i;
x3[i] = 4*i;
}
int counter = 0;
while(counter < 1000){
unsigned int p;
unsigned int q;
unsigned long long start = 0;
unsigned long long end = 0;
double m = 0;
double n = 0;
start = __rdtscp(&p);
for(int i=0; i < 500; i++){
double a = x1[i];
double b = x2[i];
unsigned long long g = x3[i];
m = m + (a * g);
n = n + (b * g);
}
end = __rdtscp(&q);
std::cout << (end-start) << "\t\t"<<m << n << std::endl;
counter++;
}
}
start = __rdtscp(&p);
rdtscp
lea r8,[rbp+6Fh]
mov dword ptr [r8],ecx
shl rdx,20h
or rax,rdx
mov r9,rax
unsigned int p;
unsigned int q;
unsigned long long start = 0;
unsigned long long end = 0;
double m = 0;
mov rdx,rbx
mov r8d,1F4h
double a = x1[i];
double b = x2[i];
unsigned long long g = x3[i];
mov rcx,qword ptr [rdx+r15]
xorps xmm1,xmm1
m = m + (a * g);
cvtsi2sd xmm1,rcx
test rcx,rcx
jns main+120h (013F32129Ch)
addsd xmm1,xmm9
movaps xmm0,xmm1
mulsd xmm0,mmword ptr [rdx+r14]
addsd xmm6,xmm0
n = n + (b * g);
mulsd xmm1,mmword ptr [rdx]
addsd xmm7,xmm1
for(int i=0; i < 500; i++){
add rdx,8
dec r8
jne main+10Ah (013F321286h)
}
end = __rdtscp(&q);
rdtscp
}
end = __rdtscp(&q);
lea r8,[rbp+6Fh]
mov dword ptr [r8],ecx
shl rdx,20h
or rdx,rax