Tôi gặp một vấn đề hiệu suất lạ trong một ma trận nhân chuẩn (matrix_mult trong Metis từ bộ MOSBENCH). Điểm chuẩn được tối ưu hóa để xếp các dữ liệu sao cho bộ làm việc đang hoạt động là 12kb (3 ô 32x32 ints) và phù hợp với bộ đệm L1. Để làm cho một câu chuyện dài ngắn, trao đổi hai vòng bên trong nhất có một sự khác biệt hiệu suất gần như 4x trên một số kích cỡ đầu vào mảng (4096, 8192) và khoảng 30% sự khác biệt trên những người khác. Vấn đề cơ bản là đi xuống để truy cập các phần tử tuần tự so với trong một mô hình sải chân. Một số kích thước mảng mà tôi nghĩ đã tạo ra một truy cập sải chân xấu tạo ra nhiều xung đột dòng bộ nhớ cache. Sự khác biệt hiệu suất là đáng kể ít hơn khi thay đổi từ 2-way kết hợp L1 đến một 8-way kết hợp L1.trình biên dịch tối ưu hóa vòng lặp lồng nhau để truy cập bộ nhớ tuần tự.
Câu hỏi của tôi là tại sao gcc không tối ưu hóa thứ tự vòng lặp để tối đa hóa truy cập bộ nhớ tuần tự?
Dưới đây là phiên bản đơn giản của sự cố (lưu ý rằng thời gian thực hiện phụ thuộc nhiều vào cấu hình L1. Các số được chỉ ra dưới đây là từ 2.3 GHZ AMD với 64K L1 liên kết 2 chiều được biên dịch với -O3).
N = ARRAY_SIZE // 1024
int* mat_A = (int*)malloc(N*N*sizeof(int));
int* mat_B = (int*)malloc(N*N*sizeof(int));
int* mat_C = (int*)malloc(N*N*sizeof(int));
// Elements of mat_B are accessed in a stride pattern of length N
// This takes 800 msec
for (int t = 0; t < 1000; t++)
for (int a = 0; a < 32; a++)
for (int b = 0; b < 32; b++)
for (int c = 0; c < 32; c++)
mat_C[N*a+b] += mat_A[N*a+c] * mat_B[N*c+b];
// Inner two loops are swapped
// Elements are now accessed sequentially in inner loop
// This takes 172 msec
for (int t = 0; t < 1000; t++)
for (int a = 0; a < 32; a++)
for (int c = 0; c < 32; c++)
for (int b = 0; b < 32; b++)
mat_C[N*a+b] += mat_A[N*a+c] * mat_B[N*c+b];
Bởi vì rất khó để chứng minh cho trình biên dịch rằng thay đổi như vậy không làm thay đổi ngữ nghĩa của thao tác. – Sven
có thể bạn thấy nó thú vị với google gcc + graphite, vốn là một nhánh đã được hợp nhất cho các phép biến đổi vòng lặp dựa trên mô hình đa diện. Có một nơi nào đó một danh sách các biến đổi có thể. –
Tôi nghĩ rằng kể từ khi bổ sung số nguyên là giao hoán mà nó sẽ khá đơn giản cho một trình biên dịch để chứng minh rằng các hoạt động là bất biến để đặt hàng looper. Tôi tự hỏi nó là gì sau đó về ví dụ mã mà làm cho nó không tầm thường để tối ưu hóa. – Mark