2011-11-27 44 views
7

nỗ lực ban đầu của tôi trông như thế này (phải chúng tôi muốn nhân)Làm cách nào để thực hiện thao tác ma trận 8 x 8 bằng SSE?

__m128 mat[n]; /* rows */ 
    __m128 vec[n] = {1,1,1,1}; 
    float outvector[n]; 
    for (int row=0;row<n;row++) { 
     for(int k =3; k < 8; k = k+ 4) 
     { 
      __m128 mrow = mat[k]; 
      __m128 v = vec[row]; 
      __m128 sum = _mm_mul_ps(mrow,v); 
      sum= _mm_hadd_ps(sum,sum); /* adds adjacent-two floats */ 
     } 
      _mm_store_ss(&outvector[row],_mm_hadd_ps(sum,sum)); 
} 

Nhưng điều này rõ ràng không hoạt động. Làm thế nào để tôi tiếp cận điều này?

tôi nên tải 4 tại một thời điểm ....

Một câu hỏi khác là: nếu mảng của tôi là rất lớn (nói n = 1000), làm thế nào tôi có thể làm cho nó 16-byte thẳng hàng? Điều đó thậm chí có thể?

+0

Bạn mong đợi kết quả gì? Tôi không thấy bất kỳ ma trận, chỉ có một phép nhân vectơ. Ngoài ra, nơi nào 3, 8 và 4 đến từ đâu? – pezcode

+0

@ user963889, kích thước không có ý nghĩa gì. Bạn đang cố làm gì vậy? Nhân một vectơ 8x1, hoặc mảng vectơ, bởi ma trận 8x8? –

+0

@BrettHale Giả sử chúng ta có 8x8 bội số một vector 8x1. Tôi muốn nhận được 8x1 kết quả. Tôi bị mắc kẹt. Các bạn có thể dẫn tôi đi đúng hướng không? Cảm ơn. – user1012451

Trả lời

4

OK ... Tôi sẽ sử dụng quy ước ma trận chính hàng. Mỗi hàng của [m] yêu cầu (2) __m128 yếu tố để mang lại 8 phao. Vector 8x1 v là một vectơ cột. Vì bạn đang sử dụng lệnh haddps, tôi sẽ giả sử SSE3 có sẵn. Tìm kiếm r = [m] * v:

void mul (__m128 r[2], const __m128 m[8][2], const __m128 v[2]) 
{ 
    __m128 t0, t1, t2, t3, r0, r1, r2, r3; 

    t0 = _mm_mul_ps(m[0][0], v[0]); 
    t1 = _mm_mul_ps(m[1][0], v[0]); 
    t2 = _mm_mul_ps(m[2][0], v[0]); 
    t3 = _mm_mul_ps(m[3][0], v[0]); 

    t0 = _mm_hadd_ps(t0, t1); 
    t2 = _mm_hadd_ps(t2, t3); 
    r0 = _mm_hadd_ps(t0, t2); 

    t0 = _mm_mul_ps(m[0][1], v[1]); 
    t1 = _mm_mul_ps(m[1][1], v[1]); 
    t2 = _mm_mul_ps(m[2][1], v[1]); 
    t3 = _mm_mul_ps(m[3][1], v[1]); 

    t0 = _mm_hadd_ps(t0, t1); 
    t2 = _mm_hadd_ps(t2, t3); 
    r1 = _mm_hadd_ps(t0, t2); 

    t0 = _mm_mul_ps(m[4][0], v[0]); 
    t1 = _mm_mul_ps(m[5][0], v[0]); 
    t2 = _mm_mul_ps(m[6][0], v[0]); 
    t3 = _mm_mul_ps(m[7][0], v[0]); 

    t0 = _mm_hadd_ps(t0, t1); 
    t2 = _mm_hadd_ps(t2, t3); 
    r2 = _mm_hadd_ps(t0, t2); 

    t0 = _mm_mul_ps(m[4][1], v[1]); 
    t1 = _mm_mul_ps(m[5][1], v[1]); 
    t2 = _mm_mul_ps(m[6][1], v[1]); 
    t3 = _mm_mul_ps(m[7][1], v[1]); 

    t0 = _mm_hadd_ps(t0, t1); 
    t2 = _mm_hadd_ps(t2, t3); 
    r3 = _mm_hadd_ps(t0, t2); 

    r[0] = _mm_add_ps(r0, r1); 
    r[1] = _mm_add_ps(r2, r3); 
} 

Đối với căn chỉnh, một biến __m128 phải được căn chỉnh tự động trên ngăn xếp. Với bộ nhớ động, đây không phải là một giả định an toàn. Một số triển khai malloc/new chỉ có thể trả về bộ nhớ được bảo đảm là liên kết 8 byte.

Tiêu đề nội tại cung cấp _mm_malloc và _mm_free. Tham số căn chỉnh phải là (16) trong trường hợp này.

+0

Cảm ơn bạn. Mã của tôi trông giống như của bạn bây giờ sau 2 ngày làm việc ... nhưng của bạn là rất rõ ràng. Tôi đã học. Cảm ơn. – user1012451

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