Vấn đề là cublas, vv được thiết kế để sử dụng tất cả các SM để nhân các ma trận lớn. Đó không phải là điều bạn muốn; bạn muốn thực hiện rất nhiều phép nhân ma trận nhỏ.
Có thể có cách nào đó để truyền nội dung này vào thứ gì đó CUBLAS có thể làm tốt cho bạn, nhưng tôi không nhìn thấy nó. Đề xuất của tôi sẽ như sau:
Viết hạt nhân sử dụng một khối chuỗi để nhân hai ma trận nhỏ của bạn và xuất kết quả.
Sau đó khởi động log kernel N với tấn khối và giải quyết những cặp nhân:
- Bước 1: nhân M x M , M x M ... M N - 2 x M N-1, xuất ra M ', M' .. M ' N/2
- Bước 2: nhân M' x M ', M' x M ' ... M' N/2 - 2 x M N/2-1, xuất ra M '' , M '' .. M '' N/4 ...
, vv
Sẽ có hệ số 50% phí trên bộ nhớ, nhưng tôi nghĩ bạn sẽ tận dụng tốt hơn lõi của bạn theo cách này.
Cập nhật
Ok, nếu bạn thực sự không muốn làm điều này trong giai đoạn, bạn có thể làm theo cách này nhưng nó sẽ đòi hỏi mã hóa hơn, và hiệu suất có lẽ sẽ tồi tệ hơn so với những gì bạn có thể nhận được một cái gì đó như cuBLAS và chuyển giao không đồng bộ. Tôi giả sử bạn đang sử dụng một Fermi, và bạn đã tắt bộ nhớ cache L1 để bạn có 48K chia sẻ mem cho mỗi SM.
Lưu trữ 100 ma trận ở dạng khối 2x2, với mỗi khối có liên quan trong bộ nhớ. Vì vậy, matrix[matrixnum,i,j]
bắt đầu tại matricies[matrixnum*100*100 + i*100*50 + j*50*50]
. Lưu ý rằng mỗi khối là 50 * 50 * 4 byte ~ 10K, do đó, 4 thoải mái phù hợp trong bộ nhớ chia sẻ.
Chỉ định mỗi chuỗi 4 chuỗi một (Nmatricies/Nblocks) chuỗi dài của ma trận để nhân lên, với một trong bốn chuỗi chịu trách nhiệm cho mỗi khối phép nhân.
Giả sử bạn đang tạo chuỗi 1 trong 4 và phần đầu tiên của ma trận bạn nhân với nhau là AxB. Bạn có trách nhiệm (1,1) của kết quả - (AB) 1,1 = A 1,1 B 1,1 + A 1,2 * B 2,1. Bạn tải trước trong A 1,1 vào khoanh vùng [0] trong bộ nhớ dùng chung.
- tải trong myblock [1] = B 1,1 từ bộ nhớ toàn cầu
- myblock [3] = myblock [0] * myblock [1] (ma trận mult, tất cả trong bộ nhớ chia sẻ)
- tải trong myblock [1] = A 1,2 từ toàn cầu
- tải trong myblock [2] = B 2,1 từ toàn cầu
- myblock [0] = myblock [3] + (myblock [ 1] * myblock [2]) (ma trận đa và bổ sung, tất cả trong bộ nhớ chia sẻ).
Bây giờ bạn có thể lặp lại điều này cho phần còn lại của chuỗi ma trận trong phần của chuỗi, chỉ xuất hiện khi hoàn tất.
Khi bạn hoàn thành, bạn sẽ kết thúc với (#SMs) ma trận trong bộ nhớ toàn cầu, vẫn phải nhân lên, nhưng sẽ không có thêm bộ nhớ tạm thời nào trong bộ nhớ toàn cầu và bạn đã thắng ' t đã phải sao chép dữ liệu vào bộ nhớ toàn cầu khác với các ma trận gốc và danh sách của những cái để giải quyết.
Một lần nữa, không có lý do thực sự để làm điều này ngoại trừ việc bạn không thể bị làm phiền khi truyền dữ liệu đến GPU theo từng giai đoạn và hiệu suất gần như chắc chắn sẽ tồi tệ hơn; có ít bộ nhớ toàn cục hơn, nhưng bạn có thể sẽ trả tiền cho nó bằng một GEMM được cuộn bằng tay. Tin tốt là 50 không phải là bội số của 8, vì vậy bạn có thể sẽ không có quá nhiều trong cách thức xung đột ngân hàng bộ nhớ chia sẻ.
Một lần nữa, đối với điểm thưởng, bạn có thể tính toán trước tất cả các khối của tất cả các sản phẩm ma trận ghép nối trước và sau đó bằng một nửa độ dài của danh sách.
Các ma trận có đặc biệt theo bất kỳ cách nào hữu ích không? Nếu họ đồng thời diagalizable này được đơn giản hơn rất nhiều. –
@JonathanDursi: Các đặc điểm duy nhất của ma trận là cho mỗi ma trận tất cả các giá trị tổng là 1. và ma trận là bậc hai, nhưng điều đó phải rõ ràng từ mô tả. –