2017-05-27 17 views
11

Tôi đang chú ý đến mã của người khác và hiện đang cố gắng tìm ra lý do tại sao _mm_load_si128 tồn tại.Tại sao có 128bit chức năng tải cho SSE?

Về cơ bản, tôi đã cố gắng thay thế

_ra = _mm_load_si128(reinterpret_cast<__m128i*>(&cd->data[idx])); 

với

_ra = *reinterpret_cast<__m128i*>(&cd->data[idx]); 

và nó hoạt động và thực hiện giống hệt nhau.

Tôi nhận thấy rằng các chức năng tải tồn tại cho các loại nhỏ hơn chỉ vì mục đích thuận tiện để mọi người không phải gói chúng vào bộ nhớ liên tục theo cách thủ công, nhưng đối với dữ liệu đã đúng thứ tự, tại sao lại bận tâm?

Có điều gì khác mà _mm_load_si128 không? Hay về cơ bản nó chỉ là một cách xoay vòng để gán một giá trị?

+0

Có thể là (hoặc được mở rộng đến) một số trình biên dịch được xây dựng. Bạn đang sử dụng trình biên dịch C++ nào? –

+0

@BasileStarynkevitch một trong số đó đi kèm với studio trực quan – user81993

+0

Không phải '_ra = reinterpret_cast <__m128> (cd-> data [idx])' cũng có thể không? – Walter

Trả lời

13

Có tải trọng rõ ràng và ngầm định trong SSE.

  • _mm_load_si128(reinterpret_cast<__m128i*>(&cd->data[idx])); là một tải rõ ràng
  • *reinterpret_cast<__m128i*>(&cd->data[idx]); là một tải ngầm

Với một tải rõ ràng bạn hướng dẫn rõ ràng các trình biên dịch để nạp dữ liệu vào một thanh ghi XMM - đây là "chính thức" Intel cách để làm điều đó. Bạn cũng có thể kiểm soát tải là tải trọng được căn chỉnh hay không thẳng hàng bằng cách sử dụng _mm_load_si128 hoặc _mm_loadu_si128.

Mặc dù là phần mở rộng, hầu hết các trình biên dịch cũng có thể tự động tạo các tải XMM khi bạn thực hiện type-punning, nhưng theo cách này bạn không thể kiểm soát việc tải được căn chỉnh hay không thẳng hàng. Trong trường hợp này, vì trên các CPU hiện đại không có hình phạt hiệu suất của việc sử dụng các tải không được căn chỉnh khi dữ liệu được căn chỉnh, các trình biên dịch có xu hướng sử dụng các tải không được sắp xếp phổ quát.

Một khía cạnh quan trọng khác là tải trọng tiềm ẩn bạn vi phạm các quy tắc strict aliasing, điều này có thể dẫn đến hành vi không xác định. Mặc dù cần lưu ý rằng - như một phần của phần mở rộng - các trình biên dịch hỗ trợ nội tại Intel không có xu hướng thực thi các quy tắc bí mật nghiêm ngặt về các loại trình giữ chỗ XMM như __m128, __m128d, __m128i.

Tuy nhiên, tôi cho rằng tải trọng rõ ràng là sạch hơn và chống đạn hơn.


Tại sao trình biên dịch không có xu hướng thực thi quy tắc bí danh nghiêm ngặt về loại trình giữ chỗ SSE?

Các lý do 1st dối trá trong việc thiết kế intrinsics SSE: có những trường hợp rõ ràng khi bạn phải sử dụng kiểu punning, vì không có cách nào khác để sử dụng một số intrinsics. Mysticial's answer tóm tắt nó một cách hoàn hảo.

Như Cody Grey đã chỉ ra trong các nhận xét, điều đáng nói đến là các công cụ MMX lịch sử (hiện giờ được thay thế bởi SSE2) thậm chí không cung cấp các tải hoặc cửa hàng rõ ràng - bạn phải sử dụng loại punning.

Lý do thứ hai (có liên quan đến số 1) nằm trong định nghĩa loại của các loại này.

GCC của typedef s cho các loại placeholder/SSE2 SSE trong <xmmintrin.h ><emmintrin.h>:

/* The Intel API is flexible enough that we must allow aliasing with other 
    vector types, and their scalar components. */ 

typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));  
typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__)); 
typedef double __m128d __attribute__ ((__vector_size__ (16), __may_alias__)); 

Mấu chốt ở đây là __may_alias__ thuộc tính, mà làm việc kiểu punning trên các loại ngay cả khi răng cưa chặt chẽ được kích hoạt với cờ -fstrict-aliasing.

Hiện tại, kể từ clangICC tương thích với GCC, chúng phải tuân thủ cùng một quy ước. Vì vậy, hiện tại, trong 3 trình biên dịch này, các tải/cửa hàng tiềm ẩn được đảm bảo làm việc ngay cả với cờ -fstrict-aliasing. Cuối cùng, MSVC không hỗ trợ bí danh nghiêm ngặt, do đó, nó thậm chí không thể là vấn đề ở đó.

Tuy nhiên, điều này không có nghĩa là bạn nên thích tải/lưu trữ ngầm hơn các cửa hàng khiêu dâm.

+0

Thành phần quan trọng đối với câu trả lời này là bí danh nghiêm ngặt — tải trọng rõ ràng tránh hành vi không xác định. Bạn có một số loại tài liệu tham khảo cho thực tế là các trình biên dịch hỗ trợ Intel nội tại không thực thi các quy tắc bí mật nghiêm ngặt về các loại XMM, hay chỉ dựa trên kinh nghiệm của riêng bạn? Tôi hỏi vì nó phù hợp với kinh nghiệm của tôi, nhưng chỉ vì một cái gì đó hoạt động không có nghĩa là nó không có nguy cơ UB! –

+0

Nó cũng có thể được thêm rằng những tải trọng rõ ràng là mới cho SSE. Chúng không được cung cấp bởi nội tại MMX, mà về cơ bản đã tạo ra các tải ngầm và các phôi xấu cần thiết cho các hoạt động tải * tất cả *. –

+0

@CodyGray Hành vi này không chính thức gắn liền với nội tại của Intel, tuy nhiên có những trường hợp hiển nhiên khi thiết kế nội tại buộc bạn sử dụng bí danh - không có cách nào khác. Tôi đề nghị câu trả lời này: https://stackoverflow.com/a/24788226/2430597. – plasmacel

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