Tôi đã cố gắng xóa trang người đàn ông GCC cho điều này, nhưng vẫn không hiểu, thực sự.
Sự khác biệt giữa -march
và là -mtune
gì?
Khi nào người ta sử dụng just -march
, so với cả hai? Có bao giờ có thể chỉ -mtune
?
Câu trả lời:
Nếu bạn sử dụng -march
thì GCC sẽ tự do tạo ra các lệnh hoạt động trên CPU được chỉ định, nhưng (thông thường) không hoạt động trên các CPU cũ hơn trong họ kiến trúc.
Nếu bạn chỉ sử dụng -mtune
, thì trình biên dịch sẽ tạo ra mã hoạt động trên bất kỳ mã nào trong số chúng, nhưng sẽ ưu tiên các chuỗi lệnh chạy nhanh nhất trên CPU cụ thể mà bạn đã chỉ định. ví dụ: thiết lập heuristics của loop-unrolling thích hợp cho CPU đó.
-march=foo
ngụ ý -mtune=foo
trừ khi bạn cũng chỉ định một khác -mtune
. Đây là một lý do tại sao việc sử dụng -march
tốt hơn là chỉ bật các tùy chọn như -mavx
mà không cần làm gì về điều chỉnh.
Lưu ý: -march=native
trên một CPU mà GCC không nhận dạng cụ thể sẽ vẫn kích hoạt các tập lệnh mới mà GCC có thể phát hiện, nhưng sẽ bỏ đi -mtune=generic
. Sử dụng GCC đủ mới biết về CPU của bạn nếu bạn muốn nó tạo mã tốt.
march
ngụ ý mtune
. Vì vậy, câu trả lời cho sự phản đối của bạn lần lượt là không và có.
mtune
và tối ưu khác nhau march
. Bài đăng trên blog này làm sáng tỏ quan điểm đó với những bài khác: lemire.me/blog/2018/07/25/…
Đây là những gì tôi đã tìm kiếm trên Google:
Các -march=X
tùy chọn có một tên CPU X
và cho phép GCC để tạo ra mã có sử dụng tất cả các tính năng của X
. Sổ tay hướng dẫn GCC giải thích chính xác tên CPU nào có nghĩa là họ và tính năng của CPU.
Bởi vì các tính năng thường được thêm vào, nhưng không bị loại bỏ, một tệp nhị phân được xây dựng với -march=X
sẽ chạy trên CPU X
, có cơ hội tốt để chạy trên các CPU mới hơn X
, nhưng gần như chắc chắn sẽ không chạy trên bất kỳ thứ gì cũ hơn X
. Một số bộ lệnh nhất định (3DNow !, tôi đoán?) Có thể dành riêng cho một nhà cung cấp CPU cụ thể, việc sử dụng chúng có thể giúp bạn nhận được các tệp nhị phân không chạy trên các CPU cạnh tranh, mới hơn hoặc bằng cách khác.
Các -mtune=Y
tùy chọn chỉnh mã được tạo để chạy nhanh hơn trên Y
hơn trên CPU khác, nó có thể chạy trên. -march=X
ngụ ý -mtune=X
. -mtune=Y
sẽ không ghi đè -march=X
, vì vậy, ví dụ, nó có thể không có ý nghĩa gì -march=core2
và -mtune=i686
- core2
dù sao mã của bạn sẽ không chạy trên bất kỳ thứ gì cũ hơn , vì -march=core2
vậy, tại sao trên Earth bạn lại muốn tối ưu hóa cho thứ gì đó cũ hơn (ít tính năng hơn) so với core2? -march=core2 -mtune=haswell
có ý nghĩa hơn: không sử dụng bất kỳ tính năng nào ngoài những gì core2
cung cấp (vẫn còn nhiều hơn những gì -march=i686
mang lại cho bạn!), nhưng hãy tối ưu hóa mã cho các haswell
CPU mới hơn nhiều , không phải cho core2
.
Còn -mtune=generic
nữa. generic
làm cho GCC tạo ra mã chạy tốt nhất trên các CPU hiện tại (nghĩa là các generic
thay đổi từ phiên bản GCC này sang phiên bản khác của GCC). Có tin đồn trên các diễn đàn Gentoo -march=X -mtune=generic
tạo ra mã chạy nhanh X
hơn mã được tạo ra -march=X -mtune=X
(hoặc chỉ -march=X
, như -mtune=X
được ngụ ý). Không biết điều này có đúng hay không.
Nói chung, trừ khi bạn biết chính xác những gì bạn cần, có vẻ như cách tốt nhất là chỉ định -march=<oldest CPU you want to run on>
và -mtune=generic
( -mtune=generic
ở đây để chống lại điều ngầm hiểu -mtune=<oldest CPU you want to run on>
, vì có thể bạn không muốn tối ưu hóa cho CPU cũ nhất). Hoặc chỉ -march=native
, nếu bạn chỉ chạy trên cùng một máy mà bạn xây dựng.
-march=native
, bạn có thể muốn chỉ định -mtune=X
, vì mặc định vẫn là -mtune=generic
, như đã thảo luận ở đây: lemire.me/blog/2018/07/25/…
-march=native
ngụ ý tune=native
chỉ tốt nếu bạn sử dụng GCC biết về CPU của bạn. Bài báo đó chỉ trình bày trường hợp xấu. Các phiên bản GCC mới hơn làm cho mã tốt hơn nói chung, đặc biệt là khi sử dụng các lệnh mới như AVX2 và AVX-512. Và có các cài đặt điều chỉnh (chẳng hạn như khám phá vòng lặp) được thiết kế cho CPU của bạn là một điểm cộng nhất định. Vì vậy, nếu bạn đủ quan tâm đến hiệu suất để sử dụng các tùy chọn này, hãy sử dụng GCC mới, ít nhất một GCC biết về CPU của bạn, tốt nhất là relese ổn định hiện tại.
tune=generic
với một thành viên mới hơn của cùng một họ vi kiến trúc, đặc biệt là một thứ như Kaby Lake, giống hệt với vi kiến trúc Skylake. Nhưng tôi nghĩ rằng nó vẫn có một họ / bước khác nên một GCC chỉ biết về Skylake trở lên có thể không nhận ra nó để điều chỉnh.