Tối ưu hóa phép nhân vectơ ma trận cho nhiều ma trận nhỏ


8

Tôi đang xem xét tăng tốc các sản phẩm vector ma trận nhưng mọi thứ tôi đọc là về cách thực hiện nó cho các ma trận rất lớn. Trường hợp của tôi, ma trận là nhỏ nhưng số lần nó phải được thực hiện là rất lớn.

Những phương pháp nào, nếu có, để tối ưu hóa điều này? Có thể nhanh hơn để xây dựng một ma trận khối đường chéo thực sự lớn ra khỏi các ma trận nhỏ và một vectơ lớn được tạo từ các vectơ nhỏ hơn và sử dụng các kỹ thuật cho việc tăng tốc vectơ ma trận lớn? Hoặc sẽ thiết lập ma trận toàn cầu và vectơ giết chết bất kỳ lợi ích nào ở đó?


Bạn có phải nhân các ma trận giống nhau nhiều lần với nhiều vectơ không hoặc không sử dụng lại các ma trận?
Brian Borchers

Tôi nghi ngờ rằng việc sử dụng các kỹ thuật cho ma trận lớn cho một đường chéo khối lớn sẽ giúp bạn tăng tốc đáng kể. Làm thế nào nhỏ 'nhỏ' trong trường hợp của bạn và chúng ta thường nói về bao nhiêu ma trận? Bạn có biết gì khác về các ma trận này không, ví dụ, chúng có mô tả các phép quay v.v. không?
Christian Waluga

@BrianBorchers Không sử dụng lại ma trận, mỗi lần mỗi bước sẽ khác nhau
tpg2114

@ChristianWaluga Chúng có kích thước 5x5 đôi khi có thể gấp 10 lần, dày đặc, không đối xứng và không chiếm ưu thế theo đường chéo nói chung. Bao nhiêu lần nó cần phải được thực hiện khác nhau tùy theo trường hợp, nhưng thường là 10000 đến 60000 lần mỗi bước thời gian
tpg2114

Câu trả lời:


7

Trước khi cố gắng tối ưu hóa mã của bạn, nên hỏi xem có gì để tối ưu hóa để bắt đầu không. Các thư viện tối ưu hóa các sản phẩm vector ma trận làm như vậy bằng cách giải quyết hai vấn đề: giới hạn về kích thước của bộ đệm và độ trễ để tải dữ liệu từ bộ nhớ. Việc đầu tiên được thực hiện bằng cách sử dụng dữ liệu hiện có trong bộ đệm đến mức tối đa cho mọi thứ nó cần được sử dụng trước khi thay thế bằng dữ liệu khác, sau đó được thực hiện bằng cách tìm nạp dữ liệu vào bộ đệm trước khi thực sự sử dụng nó.

Trong trường hợp của bạn, bạn có cường độ số học tương đối ít - bạn tải dữ liệu từ bộ nhớ, bạn sử dụng chính xác một lần và sau đó bạn chuyển sang ma trận tiếp theo. Điều này chỉ để lại con đường thứ hai để tối ưu hóa cho: tìm nạp dữ liệu trước khi bạn sử dụng nó.

Nhưng, như tôi đã nói, trước khi cố gắng tối ưu hóa mọi thứ, có thể đáng để tìm ra những gì bạn đã có: thời gian bạn đang làm bao nhiêu sản phẩm vector ma trận mỗi giây, tính toán số lượng byte này cần để tải từ bộ nhớ vào bộ xử lý của bạn, và sau đó so sánh điều này với băng thông của bộ xử lý mà bạn có trong máy. Bạn có thể thấy rằng không có gì bạn có thể làm để làm mọi thứ nhanh hơn.


4

Nó có thể không thực sự quan trọng vì ma trận của bạn đã có bộ nhớ cache, nhưng bạn nên gọi dgemv()hoặc sgemv()hoặc tương đương từ thư viện BLAS tốt nhất mà bạn có thể có được. Bạn nên dùng thử Intel MKL nếu bạn có thể truy cập vào nó, và cả BLIS hoặc ATLAS hoặc một trong nhiều thư viện BLAS được tối ưu hóa khác ngoài kia.


1
Điều thú vị là các thói quen BLAS chạy chậm hơn chức năng nội tại MATMUL trong Fortran, ngay cả với MKL và các triển khai cụ thể về phần cứng.
tpg2114

1
Tôi không hoàn toàn ngạc nhiên về điều đó, nhưng tôi phải xem mã để biết chắc chắn. Có một số vấn đề phải lo lắng. Tôi sẽ phải đề nghị kiểm tra sự liên kết của các mảng của bạn trước khi viết MKL, nhưng ở các kích thước nhỏ này, MKL MATVEC có thể không được tối ưu hóa mạnh mẽ.
Bill Barth

Bill, một đồng nghiệp của tôi cũng gặp phải vấn đề tương tự. Kết luận là có một số chi phí không đáng kể trong cuộc gọi MKL hoặc mặt khác nó không được tối ưu hóa tốt cho các ma trận nhỏ. Dù bằng cách nào, một matmul viết tay đã nhanh hơn đáng kể khi thực hiện một số lượng lớn các phép nhân ma trận 5x5.
Aurelius

2
Matmul cho một NxN nhân một Nx1 nên có các phép toán . Làm thế nào bạn đến ? O ( N 3 )O(N2)O(N3)
Bill Barth

3
Nếu ma trận rất nhỏ (ví dụ: 4 x 4), hãy thử cho một trong các thư viện templated đi - nó có thể loại bỏ rất nhiều chức năng gọi qua chức năng. Eigen là một ứng cử viên tốt.
Damien

4

Tạo mã C ++ và sử dụng Eigen / Armadillo là một khả năng, nhưng điều này phụ thuộc vào ứng dụng.

Giải pháp cho chúng tôi là chỉ cần viết ra kết quả rõ ràng cho . Không có các vòng lặp, mã rất nhanh với các trình biên dịch hiện đại và hỗ trợ vector (sse2, avx2 và avx512 trong 64 bit).N<8

Đừng quan tâm đến việc căn chỉnh bộ nhớ dữ liệu của bạn (tối đa 64 byte được căn chỉnh) và hạn chế các con trỏ để làm cho trình biên dịch dễ dàng hơn. Không cần sử dụng hỗ trợ đa lõi với các kích thước ma trận này, chi phí hoạt động lớn hơn mức tăng.

Chúng tôi sử dụng kịch bản để tự động tạo các chức năng riêng biệt cho từng kết hợp có thể và lưu trữ các con trỏ hàm cho các cuộc gọi liên tiếp.

Có một thư viện giá rẻ đẹp cho các hoạt động ma trận nhỏ được tối ưu hóa bằng tay, được gọi là OptiVec , và nó hoạt động rất tốt trong trường hợp của chúng tôi. Chúng tôi sử dụng nó cho .N8

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.