Tôi có một thư viện chứa một số thuật toán xử lý hình ảnh, bao gồm thuật toán vùng quan tâm (cắt xén). Khi được biên dịch bằng GCC, trình tự động vector hóa sẽ tăng tốc nhiều mã nhưng sẽ làm giảm hiệu suất của thuật toán Cắt. Có cách nào để đánh dấu một vòng lặp nhất định mà bộ tạo vectơ bỏ qua hoặc có cách nào tốt hơn để cấu trúc mã để có hiệu suất tốt hơn không?
cho (RowIndex=0;RowIndex<>
{
rowOffsetS = ((OriginY + RowIndex) * SizeX) + OriginX;
rowOffsetD = (RowIndex * Destination.GetColumns());
cho (ColumnIndex=0;ColumnIndex<>
{
BufferSPtr=Bộ đệm + rowOffsetS + ColumnIndex;
BufferDPtr=BufferD + rowOffsetD + ColumnIndex;
*Bộ đệmDPtr=*Bộ đệmSPtr;
}
}
在哪里Kích thướcX
là chiều rộng của mã nguồnNguồn gốcX
là phía bên trái của khu vực quan tâmXuất xứY
là đỉnh của vùng quan tâm
Tôi chưa tìm thấy bất cứ điều gì về việc thay đổi cờ tối ưu hóa vòng lặp, nhưng theo tài liệu bạn có thể sử dụng các thuộc tính trên các hàm tối ưu hóa
(Kiểm tra đây Và đây ) để ghi đè cài đặt tối ưu hóa của hàm như thế này:
void foo() __attribute__((tối ưu hóa("O2", "hàm nội tuyến")))
Nếu bạn muốn thay đổi nó cho nhiều chức năng, bạn có thể sử dụng #pragma tối ưu hóa GCC
cho tất cả các chức năng sau (nhìn vào đây) để thiết lập nó.
Do đó, bạn sẽ có thể biên dịch các hàm chứa crop với một bộ cờ tối ưu hóa khác, bỏ qua quá trình tự động vector hóa. Điều này có nhược điểm là mã hóa cứng các cờ biên dịch cho hàm, nhưng đó là điều tốt nhất tôi tìm thấy.
Về việc sắp xếp lại để có hiệu suất tốt hơn, tôi đã nghĩ đến hai điểm tôi đã đề cập trong phần nhận xét (giả sử các phạm vi không thể trùng nhau):
Khai báo con trỏ là __restrict
để báo cho trình biên dịch biết rằng chúng không có bí danh (vùng được trỏ tới bởi con trỏ sẽ không được truy cập theo bất kỳ cách nào khác trong hàm). Khả năng đặt bí danh con trỏ là một trở ngại lớn đối với trình tối ưu hóa, bởi vì nếu nó không biết về cách viết Bộ đệmD
liệu nó có thay đổi không nội dung của BufferS<, nó không thể dễ dàng sắp xếp lại để truy cập
.
Thay thế vòng lặp bên trong bằng lệnh gọi sao chép:
std::copy(BufferS + rowOffsetS, BufferS + rowOffsetS + Destination.GetColumns(), BufferD + rowOffsetD);
sao chép
Chức năng này có thể được tối ưu hóa tốt (có thể chuyển tiếp các đối số tới ghi nhớ
), vì vậy điều này có thể làm cho mã của bạn nhanh hơn nhưng cũng ngắn hơn (luôn là một điểm cộng).
Tôi là một lập trình viên xuất sắc, rất giỏi!