2010-10-19 26 views
5

Tôi rất mới đối với SSE và đã tối ưu hóa một phần mã bằng nội tại. Tôi hài lòng với bản thân chiến dịch, nhưng tôi đang tìm cách tốt hơn để viết kết quả. Kết quả sẽ kết thúc trong ba biến số _m128i.Làm thế nào để lưu trữ các giá trị trong các vị trí bộ nhớ không tiếp giáp với SSE nội tại?

Điều tôi đang cố gắng lưu trữ các byte cụ thể từ các giá trị kết quả đến các vị trí bộ nhớ không tiếp giáp. Tôi hiện đang làm điều này:

__m128i values0,values1,values2; 

/*Do stuff and store the results in values0, values1, and values2*/ 

y[0]  = (BYTE)_mm_extract_epi16(values0,0); 
cb[2]=cb[3] = (BYTE)_mm_extract_epi16(values0,2); 
y[3]  = (BYTE)_mm_extract_epi16(values0,4); 
cr[4]=cr[5] = (BYTE)_mm_extract_epi16(values0,6); 

cb[0]=cb[1] = (BYTE)_mm_extract_epi16(values1,0); 
y[1]  = (BYTE)_mm_extract_epi16(values1,2); 
cr[2]=cr[3] = (BYTE)_mm_extract_epi16(values1,4); 
y[4]  = (BYTE)_mm_extract_epi16(values1,6); 

cr[0]=cr[1] = (BYTE)_mm_extract_epi16(values2,0); 
y[2]  = (BYTE)_mm_extract_epi16(values2,2); 
cb[4]=cb[5] = (BYTE)_mm_extract_epi16(values2,4); 
y[5]  = (BYTE)_mm_extract_epi16(values2,6); 

đâu y, cb, và cr là byte (unsigned char) mảng. Điều này có vẻ sai với tôi vì lý do tôi không thể xác định. Có ai có bất cứ đề nghị cho một cách tốt hơn?

Cảm ơn!

+0

Tôi nghĩ bạn đang tìm kiếm một trong các nội dung _mm_packXxx. –

+0

Tôi nhìn vào những thứ đó, nhưng không ai trong số họ dường như làm những gì tôi muốn. Tôi sẽ đi kiểm tra một lần nữa, cảm ơn. – Scott

Trả lời

9

Về cơ bản bạn không thể - SSE không có kho lưu trữ phân tán và tất cả đều được thiết kế xung quanh ý tưởng làm việc vectơ trên luồng dữ liệu liền nhau. Thực sự, hầu hết công việc liên quan đến việc tạo một cái gì đó SIMD sắp xếp lại dữ liệu của bạn để nó tiếp giáp và có thể véc tơ. Vì vậy, điều tốt nhất cần làm là sắp xếp lại cấu trúc dữ liệu của bạn để bạn có thể viết cho chúng 16 byte cùng một lúc. Đừng quên rằng bạn có thể sắp xếp lại các thành phần bên trong vector SIMD của bạn trước khi bạn cam kết chúng vào bộ nhớ.

Nếu không, số PEXTRW op (_mm_extract_epi16 nội tại) là cách duy nhất để rút ngắn từ thanh ghi SSE và lưu vào sổ đăng ký số nguyên. Cách tiếp cận khác có sẵn cho bạn là sử dụng giải nén và phát ngẫu nhiên (_mm_shuffle_ps v.v.) để xoay dữ liệu vào từ thấp của thanh ghi và sau đó MOVSS/_mm_store_ss() để lưu từ đó vào bộ nhớ thấp tại một thời điểm. Bạn có thể thấy rằng sử dụng một liên minh, hoặc di chuyển dữ liệu giữa SSE và thanh ghi mục đích chung, sẽ cung cấp hiệu suất rất kém do chi tiết triển khai CPU tinh tế được gọi là load - hit - store gian hàng.Về cơ bản, không có cách nào trực tiếp để di chuyển dữ liệu giữa các loại đăng ký; bộ vi xử lý đầu tiên phải ghi dữ liệu SSE vào bộ nhớ, và sau đó đọc lại nó vào GPR. Trong nhiều trường hợp, điều này có nghĩa là nó phải ngừng hoạt động tải và đợi cho đến khi cửa hàng xóa trước khi có thể chạy thêm bất kỳ hướng dẫn nào.

+0

Cảm ơn lời giải thích. Khi bạn nói tôi có thể sắp xếp lại các thành phần trong vector SIMD, bạn có đề cập đến việc giải nén và phát ngẫu nhiên không? – Scott

+0

Vâng, chính xác như vậy. – Crashworks

+1

Và đừng quên bạn cũng có thể sử dụng các chuyển động được che giấu. Ví dụ: nếu bạn đã đăng ký SSE a = <'ABCD'> mà bạn muốn ghi vào dòng bộ nhớ 'XYZW' sao cho chỉ có các từ đầu tiên và thứ ba bị ghi đè (sinh ra' AYCW' trong bộ nhớ), thì bạn có thể tải dòng đích vào đăng ký b = 'XYZW', kết hợp chúng với một mặt nạ di chuyển đến c = (ABCD & 1010) | (XYZW & 0101) = AYCW, và sau đó lưu lại c vào bộ nhớ. – Crashworks

2

Tôi không biết cụ thể về SSE, nhưng nhìn chung, toàn bộ điểm của đơn vị vectorised là chúng có thể hoạt động rất nhanh với điều kiện dữ liệu tuân theo sự định hướng và định dạng cụ thể. Vì vậy, tùy thuộc vào bạn để cung cấp và trích xuất dữ liệu theo đúng định dạng và căn chỉnh.

0

Bạn có thể thử sử dụng công đoàn để trích xuất các byte.

union 
{ 
    float value; 
    unsigned char ch[8]; 
}; 

và sau đó gán các byte khi cần thiết
Chơi xung quanh với công đoàn-ý tưởng, có lẽ thay thế các char ch unsigned [8] với một cấu trúc vô danh?
Có thể bạn có thể nhận thêm một số ý tưởng từ here

+0

Tôi nghĩ rằng thực tế là xấu để truy cập trực tiếp vào công đoàn? – Scott

+0

Tôi không biết về điều đó; giải pháp hiệu quả đơn giản nhất nhận được phiếu bầu của tôi mỗi lần – slashmais

+0

Ngoại trừ trong trường hợp này, nó gây ra một gian hàng tải trọng lớn. – Crashworks

2

SSE không có chức năng phân tán/thu thập mà bạn cần, mặc dù điều này có thể đến trong các cấu trúc SIMD trong tương lai.

Như đã được đề nghị, bạn có thể sử dụng một sự kết hợp, ví dụ:

typedef union 
{ 
    __m128i v; 
    uint8_t a8[16]; 
    uint16_t a16[8]; 
    uint32_t a32[4]; 
} U128; 

Lý tưởng nhất là loại thao tác chỉ xảy ra bên ngoài bất kỳ vòng quan trọng, vì nó là rất không hiệu quả so với các hoạt động SIMD đơn giản trên các yếu tố dữ liệu tiếp giáp .

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