2015-08-07 13 views
8

Tôi đã có một số mã 32bit đơn giản tính toán sản phẩm của một mảng các số nguyên 32 bit. Vòng lặp bên trong trông như thế này:Tại sao chuyến đi khứ hồi của bộ nhớ nhanh hơn không thực hiện chuyến đi khứ hồi?

@@loop: 
mov esi,[ebx] 
mov [esp],esi 
imul eax,[esp] 
add ebx, 4 
dec edx 
jnz @@loop 

Những gì tôi đang cố gắng để hiểu là tại sao đoạn code trên là nhanh hơn so với hai phiên bản của mã này, mà không thực hiện việc dư thừa bộ nhớ khứ hồi 6%:

@@loop: 
mov esi,[ebx] 
imul eax,esi 
add ebx, 4 
dec edx 
jnz @@loop 

@@loop: 
imul eax,[ebx] 
add ebx, 4 
dec edx 
jnz @@loop 

hai mảnh thứ hai của mã thực thi trong hầu như cùng một lúc, và như đã đề cập cả hai đều chậm hơn so với phần đầu tiên (165ms 155ms vs, 200 triệu phần tử) 6%.

Tôi đã thử căn chỉnh mục tiêu nhảy theo cách thủ công thành ranh giới 16 byte, nhưng nó không có sự khác biệt.

Tôi đang chạy tính năng này trên Intel i7 4770k, Windows 10 x64.

Lưu ý: Tôi biết mã có thể được cải thiện bằng cách thực hiện tất cả các loại tối ưu hóa, tuy nhiên, tôi chỉ quan tâm đến hiệu suất khác biệt giữa các đoạn mã trên.

+0

Tôi không thể cung cấp cho bạn tài liệu tham khảo (vì chúng có thể không tồn tại, vì chúng tiết lộ bí mật thương mại), nhưng có thể bạn đang thấy một nỗ lực phi thường mà Intel đưa vào hiệu suất bộ nhớ cache L1. – Gene

+2

Điều này vẫn xảy ra khi bạn chèn một tải giả 'mov ecx, [ebx]' vào phiên bản thứ hai? – harold

+0

Hiệu suất trong trường hợp được lưu trong bộ nhớ cache như thế nào? Vòng lặp đầu tiên sẽ phát hành bộ đệm vòng lặp tại một trong hai chu kỳ (vì nó là 5 uops-fop-domain uops trên CPU Haswell của bạn). Hai loại kia có thể phát hành tại một chu kỳ mỗi lần lặp. Tuy nhiên, chuỗi phụ thuộc 'vòng lặp' phụ thuộc vòng lặp nên hạn chế tất cả 3 chu trình trên mỗi lần lặp.Việc đầu tiên không có các cửa hàng và tải lại trong chuỗi phụ thuộc đường dẫn quan trọng, và Haswell có thể thực hiện 2x tải + 1x lưu trữ mỗi chu kỳ. (Pre-Haswell không có một cửa hàng chuyên dụng AGU). Tôi không thể thấy tại sao nó nhanh hơn, nhưng nó có nghĩa là nó không chậm hơn. –

Trả lời

1

tôi nghi ngờ nhưng không thể chắc chắn rằng bạn đang ngăn một gian hàng trên một sự phụ thuộc dữ liệu:

Mã này trông như thế này:

@@loop: 
    mov esi,[ebx] # (1)Load the memory location to esi reg 
    (mov [esp],esi) # (1)optionally store the location on the stack  
    imul eax,[esp] # (3) Perform the multiplication 
    add ebx, 4  # (1) Add 4 
    dec edx   # (1)decrement counter 
    jnz @@loop  # (0**) loop 

Những con số trong ngoặc là độ trễ của các hướng dẫn ... mà nhảy là 0 nếu dự đoán chi nhánh đoán chính xác (mà vì nó chủ yếu sẽ lặp nó sẽ hầu hết thời gian).

Vì vậy: trong khi phép nhân vẫn đang đi (3 hướng dẫn), chúng tôi quay lại đầu vòng lặp sau 2 và thử tải vào bộ nhớ và phải dừng lại. Hoặc chúng ta có thể làm một cửa hàng ... mà chúng ta có thể làm cùng lúc với phép nhân của chúng ta và sau đó không dừng lại.

Còn cửa hàng giả bạn hỏi thì sao? Tại sao nó hoạt động? Lưu ý rằng bạn đang lưu trữ giá trị quan trọng mà chúng ta đang sử dụng để nhân với bộ nhớ. Do đó, bộ xử lý có thể sử dụng giá trị này đang được lưu trữ trong bộ nhớ và ghi đè thanh ghi.

Vậy tại sao bộ xử lý không thể thực hiện việc này? Bộ vi xử lý không thể tạo nhiều truy cập bộ nhớ hơn bạn yêu cầu hoặc nó có thể can thiệp vào các chương trình đa bộ xử lý (hãy tưởng tượng rằng dòng bộ nhớ cache mà bạn đang viết được chia sẻ và bạn phải vô hiệu hóa nó trên các CPU khác mỗi vòng lặp bằng cách ghi vào nó ... ouch!).

Tất cả điều này là đầu cơ thuần túy, nhưng nó có vẻ phù hợp với tất cả các bằng chứng (mã của bạn và kiến ​​thức của tôi về kiến ​​trúc intel ... và lắp ráp x86). Hy vọng rằng ai đó có thể chỉ ra nếu tôi có điều gì đó sai trái.

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