Tôi đang thực hiện phép nội suy song tuyến trong một vòng lặp chặt chẽ và cố gắng tối ưu hóa nó với SSE, nhưng tôi không tăng tốc từ nó.Nội suy song song SSE
Đây là mã, phiên bản phi SIMD sử dụng một cấu trúc đơn giản vector có thể được định nghĩa là struct Vec3f { float x, y, z; }
với những hoạt động nhân và bổ sung thực hiện:
#ifdef USE_SIMD
const Color c11 = pixelCache[y1 * size.x + x1];
const Color c12 = pixelCache[y2 * size.x + x1];
const Color c22 = pixelCache[y2 * size.x + x2];
const Color c21 = pixelCache[y1 * size.x + x2];
__declspec(align(16)) float mc11[4] = { 1.0, c11.GetB(), c11.GetG(), c11.GetR() };
__declspec(align(16)) float mc12[4] = { 1.0, c12.GetB(), c12.GetG(), c12.GetR() };
__declspec(align(16)) float mc22[4] = { 1.0, c22.GetB(), c22.GetG(), c22.GetR() };
__declspec(align(16)) float mc21[4] = { 1.0, c21.GetB(), c21.GetG(), c21.GetR() };
// scalars in vector form for SSE
const float s11 = (x2-x)*(y2-y);
const float s12 = (x2-x)*(y-y1);
const float s22 = (x-x1)*(y-y1);
const float s21 = (x-x1)*(y2-y);
__declspec(align(16)) float ms11[4] = {1.0, s11, s11, s11};
__declspec(align(16)) float ms12[4] = {1.0, s12, s12, s12};
__declspec(align(16)) float ms22[4] = {1.0, s22, s22, s22};
__declspec(align(16)) float ms21[4] = {1.0, s21, s21, s21};
__asm {
movaps xmm0, mc11
movaps xmm1, mc12
movaps xmm2, mc22
movaps xmm3, mc21
movaps xmm4, ms11
movaps xmm5, ms12
movaps xmm6, ms22
movaps xmm7, ms21
mulps xmm0, xmm4
mulps xmm1, xmm5
mulps xmm2, xmm6
mulps xmm3, xmm7
addps xmm0, xmm1
addps xmm0, xmm2
addps xmm0, xmm3
movaps mc11, xmm0
}
#else
const Vec3f c11 = toFloat(pixelCache[y1 * size.x + x1]);
const Vec3f c12 = toFloat(pixelCache[y2 * size.x + x1]);
const Vec3f c22 = toFloat(pixelCache[y2 * size.x + x2]);
const Vec3f c21 = toFloat(pixelCache[y1 * size.x + x2]);
const Vec3f colour =
c11*(x2-x)*(y2-y) +
c21*(x-x1)*(y2-y) +
c12*(x2-x)*(y-y1) +
c22*(x-x1)*(y-y1);
#endif
Sắp xếp lại mã asm để tái sử dụng các thanh ghi (đã kết thúc chỉ với ba thanh ghi xmm) không có hiệu lực. Tôi cũng đã thử sử dụng nội tại:
// perform bilinear interpolation
const Vec3f c11 = toFloat(pixelCache[y1 * size.x + x1]);
const Vec3f c12 = toFloat(pixelCache[y2 * size.x + x1]);
const Vec3f c22 = toFloat(pixelCache[y2 * size.x + x2]);
const Vec3f c21 = toFloat(pixelCache[y1 * size.x + x2]);
// scalars in vector form for SSE
const float s11 = (x2-x)*(y2-y);
const float s12 = (x2-x)*(y-y1);
const float s22 = (x-x1)*(y-y1);
const float s21 = (x-x1)*(y2-y);
__m128 mc11 = _mm_set_ps(1.f, c11.b, c11.g, c11.r);
__m128 mc12 = _mm_set_ps(1.f, c12.b, c12.g, c12.r);
__m128 mc22 = _mm_set_ps(1.f, c22.b, c22.g, c22.r);
__m128 mc21 = _mm_set_ps(1.f, c21.b, c21.g, c21.r);
__m128 ms11 = _mm_set_ps(1.f, s11, s11, s11);
__m128 ms12 = _mm_set_ps(1.f, s12, s12, s12);
__m128 ms22 = _mm_set_ps(1.f, s22, s22, s22);
__m128 ms21 = _mm_set_ps(1.f, s21, s21, s21);
mc11 = _mm_mul_ps(mc11, ms11);
mc12 = _mm_mul_ps(mc12, ms12);
mc22 = _mm_mul_ps(mc22, ms22);
mc21 = _mm_mul_ps(mc21, ms21);
mc11 = _mm_add_ps(mc11, mc12);
mc11 = _mm_add_ps(mc11, mc22);
mc11 = _mm_add_ps(mc11, mc21);
Vec3f colour;
_mm_storeu_ps(colour.array, mc11);
Và không có kết quả. Tôi đang thiếu một cái gì đó, hoặc nó không thể đạt được bất kỳ tốc độ thêm ở đây?
Tôi ghét phải nói điều này, nhưng điều này chắc chắn không phải là cách tiếp cận đúng . Đầu tiên, bạn dành rất nhiều công việc chỉ cần điền các vectơ (mà là nguyên chất trên đầu). Sau đó, bạn có một chuỗi phụ thuộc khó chịu ở phần cuối của tính toán. Nhưng về cơ bản, vấn đề chính là bạn đang sử dụng mảng đóng gói. Nếu bạn nghiêm túc về SIMD, bạn nên xem xét chuyển sang cấu trúc của mảng. – Mysticial
Ok, tôi đã biết về việc điền các vectơ, tôi sẽ cố gắng sắp xếp lại dữ liệu ở vị trí đầu tiên để tôn trọng căn chỉnh. Nhưng bạn có thể vui lòng giải thích về "chuỗi phụ thuộc vào cuối tính toán" không? – SimpleMan
Bạn có 3 bổ sung phụ thuộc vào nhau. Vì vậy, không ai trong số họ có thể được thực hiện song song bởi vì người ta phải hoàn thành trước khi bạn bắt đầu kế tiếp. Tôi thấy rằng bạn đang làm một số loại giảm - đó là tối ưu thực hiện bằng cách sử dụng một cây nhị phân giảm. Ngay bây giờ bạn chỉ kết hợp 4 vectơ. Vì vậy, không có nhiều để đạt được không có vấn đề làm thế nào để sắp xếp lại nó. Nhưng tôi nghi ngờ rằng trong bức tranh lớn hơn, bạn đang thực sự tổng hợp một số lớn hơn nhiều số. – Mysticial