Cách tốt nhất để xác định số lượng không số không trong phép nhân ma trận thưa thớt là gì?


17

Tôi đã tự hỏi liệu có một phương pháp nhanh và hiệu quả để tìm ra số lượng không số không trước cho hoạt động nhân ma trận thưa thớt giả sử cả hai ma trận đều ở định dạng CSC hoặc CSR.

Tôi biết có một gói trong smmp nhưng tôi cần một cái gì đó đã được triển khai trong C hoặc C ++.

Bất kỳ trợ giúp sẽ được đánh giá cao. Cảm ơn trước.


ma trận của bạn có bất kỳ đối xứng, hoặc một cấu trúc đến vị trí của các mục khác không?
Godric Seer

@GodricSeer ... không
Recker

Cá nhân tôi không thể nghĩ ra bất kỳ cách nào để tính toán con số đó theo thứ tự thấp hơn là chỉ thực hiện phép nhân ma trận thực tế mà không khai thác một số đối xứng hoặc cấu trúc. Tôi giả sử bạn muốn điều này để phân bổ bộ nhớ trước khi thực hiện phép nhân?
Godric Seer

Ngoài ra, tôi đã tìm thấy bài viết này mô tả cách ước tính số lượng trên một sản phẩm ma trận boolean (giống hệt như việc đếm các phần tử trong bất kỳ sản phẩm ma trận nào).
Godric Seer

@ GodricSeer..Có bạn đúng Tôi cần số chính xác chỉ để cấp phát bộ nhớ cho ma trận kết quả. Cảm ơn liên kết đến giấy mặc dù. Điều đó có thể khiến tôi bắt đầu theo hướng nào đó trong một thời gian.
Recker

Câu trả lời:


14

Bạn chỉ có thể mô phỏng sản phẩm ma trận ma trận bằng cách tạo thành sản phẩm của hai mẫu độ thưa - tức là bạn xem xét mẫu độ thưa (được lưu trữ trong các mảng riêng biệt ở định dạng CSR) dưới dạng ma trận chứa 0 hoặc một trong mỗi mục. Thực hiện sản phẩm mô phỏng này chỉ yêu cầu bạn hình thành hoạt động trên các số 0 và số này và do đó nhanh hơn nhiều so với sản phẩm ma trận thực tế - thực tế, tất cả những gì bạn phải làm là đi qua các hàng và cột của hai ma trận và xác minh rằng có ít nhất một mục trong một hàng và cột bạn nhân với trong đó cả hai ma trận đều khác không. Đây là một hoạt động rẻ tiền - trong mọi trường hợp rẻ hơn nhiều so với việc thực hiện phép nhân dấu phẩy động trong sản phẩm thực tế, nó không chỉ yêu cầu bạn thực hiện số học dấu phẩy động (đắt tiền) mà còn đọc được các số dấu phẩy động thực tế từ bộ nhớ ( thậm chí đắt hơn, nhưng bạn không cần điều đó khi nhân mẫu độ thưa vì các giá trị khác không của ma trận được lưu trữ riêng trong CSR).


6
Điều này được gọi là phép nhân tượng trưng. Nó không nhất thiết phải rẻ hơn so với phép nhân số, đặc biệt là song song, nhưng nó chỉ cần được thực hiện một lần cho mỗi mẫu thưa. Nhiều thuật toán sẽ thực hiện thao tác nhiều lần với các giá trị số khác nhau nhưng cùng một kiểu thưa thớt, trong trường hợp đó phép nhân biểu tượng có thể được sử dụng lại.
Jed Brown

Đó là một ý tưởng hay, nhưng với hàng triệu bóng bán dẫn đang hoạt động song song * nổi song song, chúng ta chỉ nói về việc tiết kiệm tốc độ 50% hoặc ở đó.
Evgeni Sergeev

1
@EvgeniSergeev - điểm không phải là tiết kiệm trong tính toán, mà là tiết kiệm trong chuyển bộ nhớ. Vì bạn dành 80% hoặc nhiều thời gian hơn ngày hôm nay để chuyển bộ nhớ cho phép nhân ma trận thưa thớt, bạn có thể tăng đáng kể nếu bạn không phải đọc / ghi dữ liệu dấu phẩy động từ / vào bộ nhớ.
Wolfgang Bangerth 15/03/2016

Bạn sẽ nói rõ sự phức tạp của phương pháp của bạn. Nếu m bởi k thì có vẻ như phương pháp của bạn yêu cầu O ( m k ) hoạt động, đúng không? CmkO(mk)
Carl Christian

O(mk)pm=kO(mplogp)O(m2)

13

Tôi thực sự đã viết mã gốc trong Matlab cho A * B, cả A và B đều thưa thớt. Phân bổ trước không gian cho kết quả thực sự là phần thú vị. Chúng tôi đã quan sát những gì Godric chỉ ra - rằng việc biết số lượng các số khác trong AB cũng tốn kém như tính toán AB.

Chúng tôi đã thực hiện ban đầu Matlab thưa thớt vào khoảng năm 1990, trước khi bài báo Edith Cohen đưa ra cách thực tế đầu tiên, nhanh chóng để ước tính kích thước của AB một cách chính xác. Chúng tôi kết hợp một công cụ ước tính kích thước kém hơn và nếu chúng tôi hết dung lượng ở giữa tính toán, tăng gấp đôi phân bổ và sao chép kết quả tính toán một phần.

Tôi không biết những gì trong Matlab bây giờ.

Một khả năng khác là tính AB một cột tại một thời điểm. Mỗi cột có thể được lưu trữ tạm thời trong một bộ tích lũy thưa thớt (xem bài viết Matlab thưa thớt để biết giải thích về những điều này) và không gian được phân bổ để giữ kích thước chính xác của cột kết quả. Kết quả sẽ ở dạng cột thưa thớt rải rác - mỗi cột trong CSC nhưng không có sự liên tục giữa các lớp - sử dụng 2 vectơ độ dài chữ số (col start, col length), chứ không phải một, làm siêu dữ liệu. Đây là một hình thức lưu trữ có thể đáng xem; nó có một sức mạnh khác - bạn có thể phát triển một cột mà không cần phân bổ lại toàn bộ ma trận.


Để triển khai GPU của tôi, cuối cùng tôi đã tìm thấy cấu trúc khác không và sau đó tìm thấy ma trận thực tế. Hiệu suất rất tệ như mong đợi. Tôi nghĩ rằng họ sử dụng phương pháp được mô tả trong cuốn sách này để nhân hai ma trận thưa thớt trên MATLAB một cách hiệu quả.
Recker

2
Thực sự tuyệt vời, cảm ơn về quan điểm lịch sử và chào mừng bạn đến với scicomp :)
Aron Ahmadia

4

Bài viết này mô tả một thuật toán để tính gần đúng kích thước của một kết quả từ sản phẩm ma trận của hai ma trận thưa thớt.

Vấn đề với việc tìm ra một số lượng chính xác các mục nhập khác không trong phép nhân ma trận thưa thớt là mỗi phần tử trong kết quả phụ thuộc vào sự tương tác của hai vectơ, cả hai đều có khả năng chứa ít nhất một vài phần tử khác không. Do đó, để tính số lượng bạn cần đánh giá các phép toán logic trên một cặp vectơ cho mọi phần tử trong kết quả. Vấn đề với điều này là nó đòi hỏi một số thao tác tương tự như số lượng thao tác cần thiết để tự tính toán sản phẩm ma trận. Theo ý kiến ​​của tôi, tôi đã đề cập đến khả năng khai thác các cấu trúc nhất định trong các phần tử khác không của ma trận gốc, tuy nhiên những khai thác tương tự cũng có thể được sử dụng để giảm công việc được thực hiện trong phép nhân ma trận.

Bạn có thể sẽ tốt hơn nếu sử dụng bài báo trên để ước tính quá mức các yêu cầu bộ nhớ, thực hiện phép nhân và sau đó cắt bớt bộ nhớ được phân bổ hoặc di chuyển ma trận kết quả sang một mảng có kích thước phù hợp hơn. Ngoài ra, các sản phẩm ma trận thưa thớt không phải là một trường hợp hiếm gặp, và tôi gần như sẽ đảm bảo rằng vấn đề này đã được giải quyết trước đây. Một chút đào sâu vào một số thư viện ma trận thưa thớt, mã nguồn mở sẽ dẫn bạn đến các thuật toán họ sử dụng để phân bổ bộ nhớ.


0

Đối với CSR hoặc CSC, bạn có đảm bảo rằng mảng các phần tử ma trận của bạn đã không có số không? Trong trường hợp đó, thật đơn giản để tìm ra có bao nhiêu phần tử khác không, sử dụng một cái gì đó tương tự như:

int nnz = sizeof(My_Array)/sizeof(long int);

Tuy nhiên nếu đây không phải là trường hợp (có vẻ hơi quá dễ dàng) những gì bạn có thể thử là giảm . Nếu mảng các phần tử ma trận của bạn rất lớn, đây có thể là cách hiệu quả nhất để tính số lượng phần tử khác không. Nhiều thư viện C / C ++ song song như Thrust (thư viện CUDA) hoặc OpenCL (mà bạn không cần GPU để sử dụng) có hỗ trợ cho việc giảm có điều kiện - cho mỗi phần tử, hãy thêm kết quả Condition(Element). Nếu bạn đặt điều kiện thành Element != 0thì bạn sẽ thêm số lượng phần tử khác. Bạn cũng có thể muốn xóa các phần tử có giá trị bằng 0 khỏi mảng các phần tử, mảng các chỉ mục hàng / cột và điều chỉnh các con trỏ cột / hàng của bạn.


cảm ơn bạn đã trả lời ... nhưng tôi đã đề cập đến các số không trong A * B trong đó A và B là các ma trận thưa thớt. Tôi cần số lượng số không trước để tôi có thể phân bổ số lượng bộ nhớ chính xác để lưu trữ ma trận kết quả.
Recker

0

Cách đơn giản nhất để thực hiện CSR là thử

std::vector< std::map<int, complex<float>> > 

để đại diện cho ma trận của bạn. Trong trường hợp đó, bạn sẽ không thực sự lo lắng về số lượng phần tử khác không, tất cả được truy cập qua

std::map< int, complex<float> >::iterator

trên mỗi hàng. Tốt ..


2
STL, khi bạn nghĩ rằng thói quen ma trận thưa thớt của bạn không thể được thực hiện chậm hơn.
Jed Brown
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.