2015-03-09 19 views
31

Tôi đang cố gắng tối ưu hóa một số phép tính ma trận và tôi đã tự hỏi liệu có thể phát hiện tại thời gian biên dịch nếu SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI [1] được kích hoạt bởi trình biên dịch? Lý tưởng nhất cho GCC và Clang, nhưng tôi có thể quản lý chỉ với một trong số họ.Làm thế nào để phát hiện SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI có sẵn tại thời gian biên dịch?

Tôi không chắc chắn điều đó là có thể và có lẽ tôi sẽ sử dụng macro của riêng mình, nhưng tôi muốn phát hiện ra nó hơn và yêu cầu người dùng chọn nó.


[1] "KCVI" là viết tắt của Knights Corner Vector tối ưu hóa Chỉ thị. Các thư viện như FFTW phát hiện/sử dụng các tối ưu hóa lệnh mới hơn.

+1

Chính xác những gì bạn muốn kiểm tra cho? Bạn có muốn kiểm tra trình biên dịch sẽ tạo ra các lệnh AVX không? Điều quan trọng cần lưu ý là chỉ vì trình biên dịch đã sẵn sàng để sản xuất chúng không có nghĩa là CPU chương trình của bạn cuối cùng sẽ chạy cũng sẽ hỗ trợ nó (ngay cả khi cả trình biên dịch và thực thi xảy ra trên cùng một máy). – ArjunShankar

+1

@ArjunShankar Tôi muốn biết nếu ví dụ avx được bật trong khi biên dịch với -mavx. –

+2

Ngoài ra, lưu ý rằng hỗ trợ CPU và hỗ trợ hệ điều hành là hai điều khác nhau. CPU có thể hỗ trợ SSE, nhưng hệ điều hành có thể không hỗ trợ SSE (yêu cầu hệ điều hành để lưu sổ đăng ký XMM trong khi chuyển ngữ cảnh). Xem, ví dụ, [Kiểm tra SSE] (http://wiki.osdev.org/SSE#Checking_for_SSE) trên wiki OSDev. – jww

Trả lời

51

Hầu hết các trình biên dịch sẽ tự động xác định:

__SSE__ 
__SSE2__ 
__SSE3__ 
__AVX__ 
__AVX2__ 

vv, bằng đường thư theo dòng lệnh chuyển mạch bạn đang đi qua. Bạn có thể dễ dàng kiểm tra điều này với gcc (hoặc trình biên dịch gcc-tương thích như kêu vang), như thế này:

$ gcc -msse3 -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __SSE__ 1 
#define __SSE2__ 1 
#define __SSE2_MATH__ 1 
#define __SSE3__ 1 
#define __SSE_MATH__ 1 

hay:

$ gcc -mavx2 -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __AVX__ 1 
#define __AVX2__ 1 
#define __SSE__ 1 
#define __SSE2__ 1 
#define __SSE2_MATH__ 1 
#define __SSE3__ 1 
#define __SSE4_1__ 1 
#define __SSE4_2__ 1 
#define __SSE_MATH__ 1 
#define __SSSE3__ 1 

hoặc chỉ cần kiểm tra các macro được xác định trước cho một xây dựng mặc định trên nền tảng cụ thể của bạn:

$ gcc -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __SSE2_MATH__ 1 
#define __SSE2__ 1 
#define __SSE3__ 1 
#define __SSE_MATH__ 1 
#define __SSE__ 1 
#define __SSSE3__ 1 

Các bộ xử lý Intel gần đây hỗ trợ AVX-512, không phải là bộ hướng dẫn khối. Người ta có thể thấy sự hỗ trợ có sẵn từ GCC (phiên bản 6.2) cho hai ví dụ dưới đây.

Đây là Knights đích:

$ gcc -march=knl -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __AVX__ 1 
#define __AVX2__ 1 
#define __AVX512CD__ 1 
#define __AVX512ER__ 1 
#define __AVX512F__ 1 
#define __AVX512PF__ 1 
#define __SSE__ 1 
#define __SSE2__ 1 
#define __SSE2_MATH__ 1 
#define __SSE3__ 1 
#define __SSE4_1__ 1 
#define __SSE4_2__ 1 
#define __SSE_MATH__ 1 
#define __SSSE3__ 1 

Đây là Skylake AVX-512:

$ gcc -march=skylake-avx512 -dM -E - < /dev/null | egrep "SSE|AVX" | sort 
#define __AVX__ 1 
#define __AVX2__ 1 
#define __AVX512BW__ 1 
#define __AVX512CD__ 1 
#define __AVX512DQ__ 1 
#define __AVX512F__ 1 
#define __AVX512VL__ 1 
#define __SSE__ 1 
#define __SSE2__ 1 
#define __SSE2_MATH__ 1 
#define __SSE3__ 1 
#define __SSE4_1__ 1 
#define __SSE4_2__ 1 
#define __SSE_MATH__ 1 
#define __SSSE3__ 1 

Intel đã tiết lộ thêm AVX-512 tập con (xem ISA extensions). GCC (phiên bản 7) hỗ trợ cờ biên dịch và các ký hiệu tiền xử lý liên quan đến việc tập con 4FMAPS, 4VNNIW, IFMA, VBMI và VPOPCNTDQ của AVX-512:

for i in 4fmaps 4vnniw ifma vbmi vpopcntdq ; do echo "==== $i ====" ; gcc -mavx512$i -dM -E - < /dev/null | egrep "AVX512" | sort ; done 
==== 4fmaps ==== 
#define __AVX5124FMAPS__ 1 
#define __AVX512F__ 1 
==== 4vnniw ==== 
#define __AVX5124VNNIW__ 1 
#define __AVX512F__ 1 
==== ifma ==== 
#define __AVX512F__ 1 
#define __AVX512IFMA__ 1 
==== vbmi ==== 
#define __AVX512BW__ 1 
#define __AVX512F__ 1 
#define __AVX512VBMI__ 1 
==== vpopcntdq ==== 
#define __AVX512F__ 1 
#define __AVX512VPOPCNTDQ__ 1 
+2

Điều đó đơn giản là hoàn hảo! –

+0

Lưu ý rằng các macro SSE sẽ không hoạt động với Visual C++. Bạn phải sử dụng _M_IX86_FP thay vào đó: https://msdn.microsoft.com/en-us/library/b0084kay.aspx –

+1

@ Rémi: vâng, điển hình tôi sợ - điều đơn giản nhất là chỉ định nghĩa các macro SSE trong dự án hoặc makefile nếu bạn buộc phải hỗ trợ MSVC. –

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