Khi nào tôi nên giảm tải công việc cho GPU thay vì CPU?


15

Các hệ thống mới hơn như OpenCL đang được tạo ra để chúng tôi có thể chạy ngày càng nhiều mã trên bộ xử lý đồ họa của mình, điều này hợp lý, bởi vì chúng tôi có thể sử dụng càng nhiều năng lượng trong hệ thống của mình càng tốt.

Tuy nhiên, với tất cả các hệ thống mới này, dường như GPU tốt hơn CPU về mọi mặt . Bởi vì GPU có thể thực hiện tính toán song song, GPU đa lõi thực sự có vẻ như chúng tốt hơn nhiều so với CPU đa lõi; bạn có thể thực hiện nhiều phép tính cùng một lúc và thực sự cải thiện tốc độ. Vẫn còn một số trường hợp trong đó xử lý nối tiếp vẫn tốt hơn, nhanh hơn và / hoặc hiệu quả hơn so với song song?



6
Không thực sự là một câu hỏi về phần cứng. Nên được đặt lại thành "khi nào lập trình CPU (s) tốt hơn lập trình GPU (s)" và đó là một câu hỏi khá hay. IMO. Xem thẻ GPGPU trong số những người khác trên SO. Nhưng kiến ​​trúc "Những gì công nghệ để sử dụng" câu hỏi ở đây là tốt hơn ở đó.
Kate Gregory

1
@Kate Góc đó dường như được bao phủ rất tốt trong câu hỏi Siêu người dùng được liên kết. Đọc qua nó, tôi hơi ngạc nhiên khi nó không được di chuyển đến đây, thành thật mà nói. Cũng có cái này trên SO. Tôi sẽ mở lại câu hỏi (vì bạn nói đúng, các khía cạnh lập trình của nó là chủ đề ở đây). Tôi hy vọng chúng ta thấy một câu trả lời không chỉ vào phạm vi bảo hiểm (xuất sắc) hiện có của vấn đề này.
Adam Lear

1
Theo quan điểm của @ Anna, tôi nghĩ rằng các câu trả lời cần nhiều hơn về việc khi nào lập trình viên nên sử dụng GPU chứ không phải là một cuộc thảo luận lý thuyết đơn thuần về sự khác biệt giữa GPU và CPU. Tôi đã chỉnh sửa tiêu đề để phản ánh điều này.

2
@RetroX Chúng tôi không thể đóng các câu hỏi dưới dạng trùng lặp nếu chúng ở trên các trang web khác nhau.
Adam Lear

Câu trả lời:


26

Tuy nhiên, với tất cả các hệ thống mới này, dường như GPU tốt hơn CPU về mọi mặt.

Đây là một sự hiểu lầm cơ bản. Các lõi GPU hiện tại vẫn còn hạn chế so với các CPU hàng đầu hiện tại. Tôi nghĩ kiến ​​trúc Fermi của NVIDIA là GPU mạnh nhất hiện có. Nó chỉ có các thanh ghi 32 bit cho số học số nguyên và ít khả năng dự đoán nhánh và thực hiện đầu cơ sau đó là bộ xử lý Intel hàng hóa hiện tại. Chip Intel i7 cung cấp ba cấp độ bộ đệm, lõi Fermi chỉ có hai và mỗi bộ đệm trên Fermi nhỏ hơn bộ đệm tương ứng trên i7. Giao tiếp giữa các lõi GPU khá hạn chế và các tính toán của bạn phải được đặt ra để phù hợp với giới hạn đó (các lõi được chia thành các khối và giao tiếp giữa các lõi trong một khối tương đối nhanh, nhưng giao tiếp giữa các khối thì chậm).

Một hạn chế đáng kể của GPU hiện tại là tất cả các lõi phải chạy cùng một mã. Không giống như các lõi trong CPU của bạn, bạn không thể yêu cầu một lõi GPU chạy ứng dụng email của bạn và một lõi khác để chạy máy chủ web của bạn. Bạn cung cấp cho GPU chức năng đảo ngược ma trận và tất cả các lõi chạy chức năng đó trên các bit dữ liệu khác nhau.

Các bộ xử lý trên GPU sống trong một thế giới biệt lập. Họ có thể điều khiển màn hình, nhưng họ không có quyền truy cập vào đĩa, mạng hoặc bàn phím.

Truy cập vào hệ thống GPU có chi phí đáng kể. GPU có bộ nhớ riêng, do đó, tính toán của bạn sẽ bị giới hạn ở dung lượng bộ nhớ trên thẻ GPU. Truyền dữ liệu giữa bộ nhớ GPU và bộ nhớ chính tương đối tốn kém. Về mặt thực tế, điều này có nghĩa là không có lợi ích gì trong việc giao một số tính toán ngắn từ CPU cho GPU, bởi vì chi phí thiết lập và phá hỏng sẽ làm mất thời gian cần thiết để thực hiện tính toán.

Điểm mấu chốt là GPU rất hữu ích khi bạn có nhiều (như hàng trăm hoặc hàng nghìn) bản sao của một phép tính dài có thể được tính song song. Các tác vụ điển hình mà điều này phổ biến là tính toán khoa học, mã hóa video và hiển thị hình ảnh. Đối với một ứng dụng như trình soạn thảo văn bản, chức năng duy nhất mà GPU có thể hữu ích là hiển thị loại trên màn hình.


hỗ trợ chính xác kép là một phần của Shader Model 5 và AMD / ATI cũng có.
Ben Voigt

@Ben, cảm ơn đã sửa. Tôi đã xóa tuyên bố không chính xác.
Charles E. Grant

11

GPU không phải là bộ xử lý chung cho CPU. Họ chuyên thực hiện một điều rất cụ thể - áp dụng cùng một mã cho một lượng lớn dữ liệu - và họ làm điều đó rất, rất tốt, tốt hơn nhiều so với CPU. Nhưng phần lớn các ứng dụng không phải là về việc áp dụng cùng một mã cho một lượng lớn dữ liệu; đó là về một vòng lặp sự kiện: chờ đợi đầu vào, đọc đầu vào, hành động trên nó và sau đó chờ thêm đầu vào. Đó là một quá trình nối tiếp khá hay và GPU hút ở "nối tiếp".

Khi bạn có một lượng lớn dữ liệu cần xử lý và mỗi mục có thể được xử lý song song, độc lập với các mục khác, sau đó tiếp tục và gửi nó đến GPU. Nhưng đừng nghĩ đây là "mô hình mới" mà mọi thứ phải được siết chặt vào.

Câu hỏi này được gắn thẻ "tối ưu hóa", vì vậy hãy nhớ coi nó là một. Áp dụng tối ưu hóa GPU trong đó kiểm tra và định hình cho thấy tối ưu hóa là cần thiết và bản chất của nhiệm vụ là tối ưu hóa GPU có thể được áp dụng. Mặt khác, đừng bận tâm với nó, vì đó sẽ là tối ưu hóa sớm hoặc không chính xác, điều này gây ra nhiều vấn đề hơn nó khắc phục.


8

Câu trả lời đơn giản là GPU hoạt động tốt nhất khi bạn cần thực hiện một phép tính khá nhỏ, khá đơn giản trên mỗi số lượng rất lớn các mục. Để thực hiện được nhiều cách này, tính toán cho từng mục phải độc lập với tính toán cho các mục khác. Nếu có (thông thường) một số phụ thuộc giữa một mục này và một mục khác, bạn thường cần tìm ra một cách nào đó để phá vỡ nó trước khi bạn sẽ nhận được nhiều từ việc thực thi mã đó trên GPU. Nếu sự phụ thuộc hoàn toàn không thể bị phá vỡ hoặc đòi hỏi quá nhiều công việc để phá vỡ, mã có thể thực thi nhanh hơn trên CPU.

Hầu hết các CPU hiện tại cũng hỗ trợ khá nhiều loại hoạt động mà GPU hiện tại đơn giản là không cố gắng hỗ trợ chút nào (ví dụ: bảo vệ bộ nhớ cho đa nhiệm).

Nhìn từ một hướng hơi khác, CPU đã được thiết kế (phần lớn) để thuận tiện cho các lập trình viên, và những người làm phần cứng đã làm hết sức mình (và tốt nhất là tốt nhất!) Để tạo ra phần cứng duy trì mô hình thuận tiện đó cho lập trình viên, nhưng vẫn thực thi càng nhanh càng tốt.

GPU đến từ những thứ hoàn toàn ngược lại: chúng được thiết kế phần lớn để thuận tiện cho nhà thiết kế phần cứng và những thứ như OpenCL đã cố gắng cung cấp một mô hình lập trình hợp lý nhất có thể với các ràng buộc của phần cứng.

Viết mã để chạy trên GPU thường sẽ tốn nhiều thời gian và công sức hơn (vì vậy sẽ tốn nhiều tiền hơn) so với làm tương tự trên CPU. Như vậy, làm như vậy chủ yếu có ý nghĩa khi / nếu một trong hai:

  1. Vấn đề là song song đến mức bạn có thể mong đợi một khoản lãi lớn từ nỗ lực tối thiểu, hoặc
  2. Tốc độ đạt được rất quan trọng đến nỗi nó biện minh cho rất nhiều công việc làm thêm.

Có một số khả năng rõ ràng cho từng loại - nhưng một số lượng lớn các ứng dụng rõ ràng thậm chí không gần với một trong số đó. Tôi sẽ khá ngạc nhiên khi thấy (ví dụ) một ứng dụng CRUD chạy trên GPU bất cứ lúc nào (và nếu có, nó có thể sẽ xảy ra vì ai đó đặt ra mục tiêu chính xác đó, không nhất thiết là bất cứ điều gì tiếp cận tối ưu tỷ lệ chi phí / lợi ích).

Thực tế là cho rất nhiều (tôi bị cám dỗ để nói "nhất") ứng dụng, một CPU điển hình là xa hơn đủ nhanh, và tiện lợi (dẫn đến những thứ như sự phát triển dễ dàng hơn các tính năng mới) lập trình là nhiều quan trọng hơn tốc độ thực hiện.


3

bạn có thể thực hiện nhiều phép tính cùng một lúc và thực sự cải thiện tốc độ.

cải thiện tốc độ? Vậy thì sao? Trong năm ngoái, tôi chỉ có thể nhớ lại một hoặc hai lần khi cần thiết. Hầu hết thời gian tôi được yêu cầu sửa đổi hoặc sửa lỗi logic, điều chỉnh cho một nguồn dữ liệu khác, để cải thiện sự tương tác của người dùng, v.v. Tốc độ duy nhất khách hàng quan tâm trong những trường hợp này là tốc độ thay đổi. "Vui lòng phát hành tính năng mới trong một tháng hoặc tốt hơn - trong hai tuần nữa".

Đừng hiểu sai ý tôi - với tư cách là một lập trình viên, tôi rất thích siết chặt các dấu CPU. Chỉ là nghệ thuật này thường không có nhu cầu cao.

Vẫn còn một số trường hợp trong đó xử lý nối tiếp vẫn tốt hơn, nhanh hơn và / hoặc hiệu quả hơn so với song song?

Tôi sẽ nói có rất nhiều trường hợp. Xử lý nối tiếp đơn giản hơn song song, điều này làm cho nó hiệu quả hơn trong mọi trường hợp khi tốc độ không phải là một yêu cầu quan trọng. Xử lý nối tiếp cho phép thực hiện dễ dàng hơn logic và giao diện người dùng phức tạp, dễ dàng hơn để chỉ định và kiểm tra, để duy trì và thay đổi.

Theo quy định, xử lý nối tiếp cho phép thể hiện rõ hơn ý định của lập trình viên và đọc mã dễ dàng hơn. Tôi muốn nói rằng nó tiết kiệm hầu hết tài nguyên quý giá và khan hiếm - bộ não của lập trình viên.


2

CPU vẫn linh hoạt hơn. Ví dụ, GPU hiệu quả hơn CPU ở độ chính xác đơn, nhưng không chính xác gấp đôi. Có nhiều thư viện cho CPU hơn là GPU.


3
Bạn có thể đi vào chi tiết hơn một chút? Bạn đã cung cấp ba tuyên bố không có thông tin hoặc giải thích về tính xác thực của chúng.

Chà, thiếu tính toán chính xác kép hiệu quả là kiến ​​thức phổ biến: en.wikipedia.org/wiki/GPGPU
quant_dev

@quant: Thông tin của bạn ít nhất 2 năm kể từ ngày: 544 GigaFLOPS nhanh hơn nhiều so với bất kỳ CPU chính thống nào.
Ben Voigt

@Ben Tôi không thấy nơi liên kết của bạn đề cập đến hiệu suất chính xác gấp đôi.
quant_dev


2

Quy tắc đơn giản là, nếu những gì bạn đang làm có thể được thực hiện theo các cấu trúc từ đại số tuyến tính và là thời gian quan trọng, hãy thực hiện nó trên GPU nếu không sử dụng CPU.

GPU không giống như số lượng lớn CPU, chúng có các đặc tính hiệu năng cực kỳ khác nhau.


Nếu đó là "thời gian quan trọng", có lẽ bạn không có thời gian để cấu hình lại GPU cho trình tạo bóng tính toán và tải lên dữ liệu. Đó là những vấn đề lớn có lợi nhất.
Ben Voigt

@Ben, tôi nghĩ rằng chúng ta có các định nghĩa khác nhau về "thời gian quan trọng", điều tôi muốn nói là tính toán nằm trên con đường quan trọng trong một khoảng thời gian đáng kể.
dan_waterworth

1

Nếu bạn cần crunching số thô, GPU là cách để đi. Tuy nhiên, tất cả các ALU đó có nghĩa là có ít bóng bán dẫn dành riêng cho mạch điều khiển dòng chảy (phân nhánh). Vì vậy, nếu bạn cần viết một cái gì đó cần nhiều luồng điều khiển phức tạp, nhiều điều kiện, v.v., thì CPU sẽ nhanh hơn.

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.