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.
Nguồn
2013-07-20 10:31:24
Bạn đã thử mọi thứ chưa? – harold
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. –