2013-07-20 35 views
8

Làm thế nào tôi có thể nhận được các phần tử tổng (giảm) của vector nổi bằng cách sử dụng nội tại của sse?Giảm SSE vector nổi

Simple mã nối tiếp:

void(float *input, float &result, unsigned int NumElems) 
{ 
    result = 0; 
    for(auto i=0; i<NumElems; ++i) 
     result += input[i]; 
} 
+3

Bạn đã thử mọi thứ chưa? – harold

+2

Bạn có thực sự xem mã được tạo không? Ít nhất kinh nghiệm của tôi với gcc là nó làm một công việc khá tốt khi thực hiện các chỉ dẫn SSE khi có thể - nhưng nó có thể yêu cầu -O3. –

Trả lời

14

Thông thường bạn tạo ra 4 tiền một phần trong vòng lặp của bạn và sau đó chỉ cần tổng hợp theo chiều ngang trên 4 yếu tố sau khi vòng lặp, ví dụ

#include <cassert> 
#include <cstdint> 
#include <emmintrin.h> 

float vsum(const float *a, int n) 
{ 
    float sum; 
    __m128 vsum = _mm_set1_ps(0.0f); 
    assert((n & 3) == 0); 
    assert(((uintptr_t)a & 15) == 0); 
    for (int i = 0; i < n; i += 4) 
    { 
     __m128 v = _mm_load_ps(&a[i]); 
     vsum = _mm_add_ps(vsum, v); 
    } 
    vsum = _mm_hadd_ps(vsum, vsum); 
    vsum = _mm_hadd_ps(vsum, vsum); 
    _mm_store_ss(&sum, vsum); 
    return sum; 
} 

Lưu ý: cho ví dụ trên a phải thẳng hàng 16 byte và n phải là một bội số của 4. Nếu sự liên kết của a không được đảm bảo sau đó sử dụng _mm_loadu_ps thay vì _mm_load_ps. Nếu n không đảm bảo là bội số của 4 thì thêm vòng vô hướng ở cuối hàm để tích lũy bất kỳ phần tử còn lại nào.

+1

Nếu mảng đầu vào có khả năng lớn, nó có giá trị có vòng quay vô hướng lúc bắt đầu, quá, chạy 0-3 lần cho đến khi đầu vào được căn chỉnh trên một ranh giới 16B cho vòng lặp SSE. Sau đó, bạn sẽ không có tải mà qua bộ nhớ cache/trang dòng làm chậm vòng lặp của bạn. Và nó có thể sử dụng 'ADDPS' với toán hạng bộ nhớ, có khả năng vi hợp nhất, giảm chi phí. Ngoài ra, bạn có thể nhận được 2 hoặc 4 chuỗi phụ thuộc, bằng cách sử dụng nhiều bộ tích lũy, vì vậy vòng lặp của bạn có thể duy trì 1 FP FP thêm mỗi chu kỳ, thay vì 1 cho mỗi (độ trễ của 'ADDPS' = 3). –

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