2014-05-07 15 views
5

Tôi có hai thiết kế mã lặp qua các vectơ có kích thước 500. Một trong các thiết kế có chứa các mảng 64-bit đôi và thiết kế thứ hai sử dụng các mảng chứa các số nguyên 32 bit. Tôi hy vọng thiết kế 32 bit sẽ nhanh hơn vì dữ liệu hữu ích hơn có thể được đóng gói trong bộ nhớ cache.Vector nhanh hơn gấp đôi 64-bit so với một sản phẩm có dấu chấm so với vectơ của int không dấu 32 bit?

Trình biên dịch MSVC, CPU Ivy Bridge, biên dịch chế độ 64 bit.

Đây là mã 1, sử dụng ints 32-bit (chạy trong chu kỳ CPU):

#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++; 
    } 
} 

sản xuất asm này (-os):

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 

Đây là mã 2, sử dụng bộ đôi 64 bit (mã chạy trong Chu kỳ CPU):

#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++; 
    } 
} 

và đây là asm (-os) sản xuất:

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 
+0

Đó là CPU 64 bit, phải không? –

+1

Các hoạt động điểm nổi có thể được thực hiện song song với các hướng dẫn CPU khác, để có thể giải thích sự khác biệt. Mặc dù việc tháo gỡ cho thấy cả hai sử dụng thanh ghi xmm nên bây giờ tôi cũng bối rối. –

+0

Câu hỏi tương tự từ diễn đàn khác với một số so sánh. [dấu chấm động so với số nguyên] (http://stackoverflow.com/questions/2550281/floating-point-vs-integer-calculations-on-modern-hardware). Từ những gì tôi hiểu, mở rộng quy trình toán học chính xác như APFLOAT thực hiện các hoạt động của họ bằng cách sử dụng dấu chấm động, nhưng tôi không biết nếu hướng dẫn loại SSE được sử dụng. – rcgldr

Trả lời

6

Sự khác biệt là việc chuyển đổi số nguyên để đôi trong các mã đầu tiên (các vectơ chứa unsigned int, sản phẩm là trong số học số nguyên, nhưng những ứng dụng tích lũy double, trong trình lắp ráp, điều này sẽ thêm hướng dẫn cvtsi2sd vào mã của bạn).

Trong mã thứ hai, bạn sử dụng gấp đôi ở khắp mọi nơi, vì vậy bạn không có chuyển đổi và mã chạy nhanh hơn.

Sự khác biệt này có thể là nhiều hơn rõ ràng hơn trên CPU có sự phân biệt chặt chẽ hơn giữa các đơn vị xử lý điểm cố định và điểm nổi (nền tảng POWER là ví dụ cho điều này). Nền tảng X86 rất tha thứ về khía cạnh đó.

Các vấn đề liên quan