Tại sao biểu thức tính toán dưới dạng nhân ma trận làm cho chúng nhanh hơn?


18

Trong hướng dẫn MNist của Google bằng cách sử dụng TensorFlow , một phép tính được thể hiện trong đó một bước tương đương với nhân một ma trận với một vectơ. Google trước tiên hiển thị một hình ảnh trong đó mỗi phép nhân số và phép cộng sẽ thực hiện phép tính được viết đầy đủ. Tiếp theo, họ hiển thị một hình ảnh trong đó thay vào đó là biểu thức nhân ma trận, cho rằng phiên bản tính toán này, hoặc ít nhất có thể nhanh hơn:

Nếu chúng ta viết nó ra dưới dạng phương trình, chúng ta sẽ nhận được:

phương trình vô hướng

Chúng ta có thể "vector hóa" thủ tục này, biến nó thành phép nhân ma trận và phép cộng vector. Điều này rất hữu ích cho hiệu quả tính toán. (Đó cũng là một cách hữu ích để suy nghĩ.)

phương trình vectơ

Tôi biết rằng các phương trình như thế này thường được viết theo định dạng nhân ma trận bởi những người thực hành máy học, và tất nhiên có thể thấy những lợi thế để làm như vậy từ quan điểm của sự căng thẳng mã hoặc hiểu toán học. Điều tôi không hiểu là tuyên bố của Google rằng việc chuyển đổi từ dạng thủ công sang dạng ma trận "rất hữu ích cho hiệu quả tính toán"

Khi nào, tại sao và làm thế nào để có thể đạt được các cải tiến hiệu suất trong phần mềm bằng cách biểu thị các phép tính dưới dạng nhân ma trận? Nếu tôi tự tính toán nhân ma trận trong hình ảnh thứ hai (dựa trên ma trận), thì tôi sẽ làm điều đó bằng cách thực hiện tuần tự từng phép tính riêng biệt được hiển thị trong hình ảnh đầu tiên (vô hướng). Đối với tôi, chúng chẳng là gì ngoài hai ký hiệu cho cùng một chuỗi tính toán. Tại sao nó khác với máy tính của tôi? Tại sao một máy tính có thể thực hiện phép tính ma trận nhanh hơn phép tính vô hướng?

Câu trả lời:


19

Điều này nghe có vẻ rõ ràng, nhưng máy tính không thực thi công thức , chúng thực thi và thời gian thực thi đó phụ thuộc trực tiếp vào mã mà chúng thực thi và chỉ gián tiếp trên bất kỳ khái niệm nào mà mã thực hiện. Hai đoạn mã giống hệt nhau có thể có các đặc tính hiệu suất rất khác nhau. Một số lý do có khả năng tăng lên trong phép nhân ma trận cụ thể:

  • Sử dụng nhiều chủ đề. Hầu như không có CPU hiện đại nào không có nhiều lõi, nhiều lõi có tới 8 và các máy chuyên dụng để tính toán hiệu năng cao có thể dễ dàng có 64 trên nhiều ổ cắm. Viết mã theo cách rõ ràng, trong một ngôn ngữ lập trình bình thường, chỉ sử dụng một trong số đó. Nói cách khác, nó có thể sử dụng ít hơn 2% tài nguyên tính toán có sẵn của máy đang chạy.
  • Sử dụng các hướng dẫn SIMD (một cách khó hiểu, điều này cũng được gọi là "vector hóa" nhưng theo một nghĩa khác so với các trích dẫn văn bản trong câu hỏi). Về bản chất, thay vì 4 hoặc 8 hoặc hơn các hướng dẫn số học vô hướng, hãy cung cấp cho CPU một lệnh thực hiện số học trên các thanh ghi 4 hoặc 8 hoặc hơn. Điều này có thể thực hiện một số tính toán (khi chúng hoàn toàn độc lập và phù hợp với tập lệnh) nhanh hơn 4 hoặc 8 lần.
  • Sử dụng bộ nhớ cache thông minh hơn . Truy cập bộ nhớ nhanh hơn nếu chúng kết hợp theo thời gian và không gian , nghĩa là truy cập liên tiếp vào các địa chỉ lân cận và khi truy cập một địa chỉ hai lần, bạn truy cập hai lần liên tiếp thay vì tạm dừng lâu.
  • Sử dụng các bộ tăng tốc như GPU. Những thiết bị này là những con thú rất khác với CPU và lập trình chúng một cách hiệu quả là một hình thức nghệ thuật của riêng nó. Ví dụ, chúng có hàng trăm lõi, được nhóm thành một nhóm vài chục lõi và các nhóm này chia sẻ tài nguyên - chúng chia sẻ một vài KiB bộ nhớ nhanh hơn nhiều so với bộ nhớ thông thường và khi bất kỳ lõi nào trong nhóm thực thi một iftuyên bố tất cả những người khác trong nhóm đó phải chờ nó.
  • Phân phối công việc trên một số máy (rất quan trọng trong siêu máy tính!) Giới thiệu một bộ đau đầu mới nhưng tất nhiên có thể cung cấp quyền truy cập vào tài nguyên máy tính lớn hơn nhiều.
  • Các thuật toán thông minh hơn. Để nhân ma trận, thuật toán O (n ^ 3) đơn giản, được tối ưu hóa đúng với các thủ thuật ở trên, thường nhanh hơn các khối con cho kích thước ma trận hợp lý, nhưng đôi khi chúng thắng. Đối với các trường hợp đặc biệt như ma trận thưa thớt, bạn có thể viết các thuật toán chuyên dụng.

Rất nhiều người thông minh đã viết rất hiệu quả cho các hoạt động đại số tuyến tính phổ biến , sử dụng các thủ thuật trên và nhiều hơn nữa và thường là ngay cả với các thủ thuật nền tảng cụ thể ngu ngốc. Do đó, chuyển đổi công thức của bạn thành phép nhân ma trận và sau đó thực hiện phép tính đó bằng cách gọi vào thư viện đại số tuyến tính trưởng thành có lợi từ nỗ lực tối ưu hóa đó. Ngược lại, nếu bạn chỉ đơn giản viết công thức theo cách rõ ràng bằng ngôn ngữ cấp cao, mã máy cuối cùng được tạo sẽ không sử dụng tất cả các thủ thuật đó và sẽ không nhanh như vậy. Điều này cũng đúng nếu bạn thực hiện công thức ma trận và thực hiện nó bằng cách gọi một thói quen nhân ma trận ngây thơ mà bạn tự viết (một lần nữa, theo cách rõ ràng).

Làm cho mã nhanh chóng có công việc , và thường khá nhiều công việc nếu bạn muốn hiệu suất cuối cùng đó. Bởi vì rất nhiều tính toán quan trọng có thể được biểu diễn dưới dạng kết hợp của một vài phép toán đại số tuyến tính, nên việc tạo mã được tối ưu hóa cao cho các hoạt động này là kinh tế. Trường hợp sử dụng chuyên ngành một lần của bạn, mặc dù? Không ai quan tâm đến điều đó ngoại trừ bạn, vì vậy tối ưu hóa cái quái gì đó không kinh tế.


4

(thưa thớt) Phép nhân vectơ ma trận có tính song song cao. Điều này rất thuận tiện nếu dữ liệu của bạn lớn và bạn có một trang trại máy chủ theo ý của bạn.

Điều này có nghĩa là bạn có thể chia ma trận và vectơ thành các khối và để các máy riêng biệt thực hiện một số công việc. Sau đó chia sẻ một số kết quả của họ với nhau và sau đó nhận được kết quả cuối cùng.

Trong ví dụ của bạn, các hoạt động sẽ như sau

  1. thiết lập một lưới các bộ xử lý, mỗi bộ giữ một Wx, y theo tọa độ của chúng trong lưới

  2. phát vector nguồn dọc theo mỗi cột (chi phí O(log height))

  3. có mỗi bộ xử lý để nhân cục bộ (chi phí O(width of submatrix * heightof submatrix))

  4. thu gọn kết quả dọc theo mỗi hàng bằng tổng (chi phí O(log width))

Hoạt động cuối cùng này là hợp lệ vì tổng là liên kết.

Điều này cũng cho phép xây dựng dự phòng và cho phép bạn tránh phải đưa tất cả thông tin vào một máy.

Đối với các ma trận 4 x 4 nhỏ như bạn thấy trong đồ họa, đó là vì cpu có các lệnh và thanh ghi đặc biệt để xử lý các hoạt động đó.


-1

Điều mang tính hướng dẫn nhất sẽ là so sánh hiệu suất của mã của bạn với hiệu suất của phép nhân ma trận được thực hiện theo phương pháp alredy.

Luôn có một số tối ưu hóa cấp thấp hơn mà bạn không nghĩ tới, ở đây bạn có thể tìm thấy một ví dụ:

https://simulationcorner.net/index.php?page=fastmatrixvector

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.