Trong lập trình phần mềm, có thể tải cả CPU và GPU ở mức 100% không?


43

Đây là một câu hỏi chung về một chủ đề mà tôi thấy thú vị khi là một game thủ: tắc nghẽn CPU / GPU và lập trình. Nếu tôi không nhầm, tôi đã hiểu rằng cả CPU và GPU đều tính toán, nhưng cái đó tốt hơn trong một số tính toán so với cái kia do sự khác biệt về kiến ​​trúc. Ví dụ, bẻ khóa băm hoặc khai thác tiền điện tử có vẻ hiệu quả hơn trên GPU so với CPU.

Vì vậy, tôi đã tự hỏi: việc có GPU ở mức tải 100% trong khi CPU ở mức 50% (chẳng hạn) là không thể tránh khỏi?

Hay chính xác hơn: Một số tính toán thường được GPU thực hiện có thể được thực hiện bởi CPU nếu lần đầu tiên ở mức tải 100%, để cả hai đều đạt được tải 100%?

Tôi đã tìm kiếm một chút về chủ đề này, nhưng đã trở lại khá trắng tay. Tôi nghĩ và hy vọng điều này có vị trí của nó trong tiểu mục này và sẵn sàng cho bất kỳ tài liệu hoặc bài giảng nào bạn có thể cung cấp cho tôi!


53
Có thể có cả CPU và GPU đều chạy cùng một vòng vô hạn NO-OPs cùng một lúc, điều này sẽ dẫn đến cả hai đều có tải 100%.
Jörg W Mittag

17
Theo quan điểm của @ Jorg, điều duy nhất được đo bằng% CPU là phần thời gian không được sử dụng để chờ các bộ xử lý khác. 100% có thể là một điều tốt nếu chương trình có hiệu quả, hoặc là một điều xấu nếu chương trình không hiệu quả. Quá nhiều thời gian, mọi người tập trung vào CPU% như thể đó là thước đo hiệu suất - không phải vậy.
Mike Dunlavey

22
Crysis ban đầu đã làm điều này chỉ tốt.
CubicleSoft

5
@MikeDunlavey bạn đưa ra một điểm tốt. Với những chiếc xe chúng tôi không đo hiệu suất của chúng bằng RPM, chúng tôi đo tốc độ.
Thuyền trưởng Man

1
@ JörgWMittag: CPU, có thể. Nhưng các hệ điều hành và GPU đã tạm dừng các bộ giải quyết vấn đề để xử lý các vòng lặp vô hạn. Cụ thể, nếu một shader không hoàn thành trong một khoảng thời gian hợp lý, nó sẽ chết và GPU được thiết lập lại.
Nicol Bolas

Câu trả lời:


62

Về mặt lý thuyết là có, nhưng thực tế nó hiếm khi xứng đáng.

Cả CPU và GPU đều hoàn thiện , do đó, bất kỳ thuật toán nào có thể được tính toán bởi một cái cũng có thể được tính toán bằng cái kia. Câu hỏi là làm thế nào nhanh và thuận tiện.

Mặc dù GPU vượt trội khi thực hiện các phép tính đơn giản giống nhau trên nhiều điểm dữ liệu của một tập dữ liệu lớn, CPU tốt hơn ở các thuật toán phức tạp hơn với nhiều nhánh. Với hầu hết các vấn đề, sự khác biệt về hiệu năng giữa việc triển khai CPU và GPU là rất lớn. Điều đó có nghĩa là sử dụng cái này để lấy công việc từ cái kia khi nó bị đình trệ sẽ không thực sự dẫn đến sự gia tăng đáng chú ý về hiệu suất.

Tuy nhiên, cái giá bạn phải trả cho việc này là bạn cần lập trình mọi thứ hai lần, một lần cho CPU và một lần cho GPU. Đó là công việc nhiều hơn gấp đôi bởi vì bạn cũng sẽ phải thực hiện logic chuyển đổi và đồng bộ hóa. Logic đó cực kỳ khó kiểm tra, vì hành vi của nó phụ thuộc vào tải hiện tại. Mong đợi rất mơ hồ và không thể tái tạo lỗi từ đóng thế này.


1
Bạn đã đề cập rằng với hầu hết các vấn đề, sự khác biệt về hiệu năng giữa việc triển khai CPU và GPU là rất lớn , tôi thực sự khá quan tâm đến mức độ chênh lệch hiệu năng. Bạn có bất kỳ số hoặc bài viết nào về điều này (ví dụ, về ví dụ về kết xuất 3D kết cấu) không? Cảm ơn câu trả lời của bạn và thời gian của bạn!
MadWard

2
Bạn có thể muốn thêm rằng có chi phí hiệu năng để đồng bộ hóa giữa CPU và GPU, vì vậy bạn thường muốn giảm thiểu số lần chuyển giữa hai. Ngoài ra, việc thêm vào các nhánh một cách ngây thơ để "không thực thi các yếu tố mà CPU đã hoạt động" sẽ không mua cho bạn bất cứ thứ gì, vì các luồng GPU hoạt động theo từng bước.
Ethan

3
@gardenhead Không có gì trong vũ trụ hỗ trợ đệ quy không giới hạn, bởi vì vũ trụ có kích thước hữu hạn và có mật độ thông tin hữu hạn. "Tính đầy đủ" của một hệ thống nói chung là một cuộc thảo luận về những gì có thể xảy ra với những ràng buộc như vậy được loại bỏ.
Random832

3
Tôi có chút nghi ngờ rằng một GPU hiện đại về mặt kỹ thuật ít nhất là gần với Turing hoàn chỉnh như một PC 80 ... tuy nhiên, nếu bạn cố chạy các thuật toán chung trên GPU, nó thường sẽ suy biến thành một bộ xử lý tuần tự cũng sẽ không nhanh hơn PC 80, do đó, tính đầy đủ của GPU trong thực tế hầu như không hữu ích hơn so với tính đầy đủ của Turing của Brainfuck .
leftaroundabout

7
@leftaroundabout GPU hiện đại hoàn thành Turing một cách tầm thường như bất kỳ CPU nào . Tính đầy đủ của Turing không liên quan gì đến: 1) hiệu suất 2) khả năng đọc của nguồn. CPU của thập niên 80 gần với TC có mọi thứ khác: chúng là TC hoặc là không (tùy chọn thứ hai là vô nghĩa).
Margaret Bloom

36

Nó không liên quan đến lập trình trò chơi. Một số mã khoa học cũng có thể sử dụng cả GPU và CPU.

Với lập trình cẩn thận và đau đớn, ví dụ như bằng cách sử dụng OpenCL hoặc CUDA , bạn có thể tải cả GPU và CPU của mình gần 100%. Rất có thể bạn sẽ cần phải viết các đoạn mã khác nhau cho GPU (được gọi là mã "kernel") và cho CPU, và một số mã keo nhàm chán (đáng chú ý là gửi vào GPU mã hạt nhân đã biên dịch).

Tuy nhiên, mã sẽ phức tạp và có lẽ bạn cần điều chỉnh nó theo phần cứng cụ thể mà bạn đang chạy, đặc biệt là vì việc truyền dữ liệu giữa GPU và CPU rất tốn kém.

Tìm hiểu thêm về điện toán không đồng nhất .

Xem thêm OpenACC , được hỗ trợ bởi các phiên bản gần đây của GCC (ví dụ: GCC 6 vào tháng 6 năm 2016)


1
Bạn nói đúng, các thẻ và tiêu đề của tôi bị đánh lừa, xóa các trò chơi và thêm hiệu suất / tối ưu hóa. Tôi không có ý nói rằng nó là độc quyền cho các trò chơi, nhưng đó là nơi tôi nhận thấy nó. Tôi nghĩ rằng nó cũng sẽ phải rất cụ thể về phần cứng. Cảm ơn câu trả lời và liên kết của bạn!
MadWard

3
Điều này sẽ khá nhiều kết thúc với hai thuật toán. Tôi đã thử nó một lần: toàn bộ hình ảnh cùng một lúc cho GPU và nhiều hình ảnh cùng một lúc cho CPU (để lạm dụng bộ nhớ cache lớn). Nó thực sự đau đớn, đặc biệt là để duy trì.
PTwr

11

Từ quan điểm siêu máy tính, tốt hơn hết là đừng suy nghĩ về tải CPU / GPU mà chỉ xác định có bao nhiêu hoạt động mà vấn đề của bạn cần và sau đó so sánh với hiệu suất cao nhất của hệ thống.

Nếu bạn nhận được 100% mức sử dụng CPU, điều đó không có nghĩa là bạn sẽ có được tất cả hiệu năng ngoài hệ thống. CPU thường có thể làm nhiều việc khác nhau cùng một lúc, nói một bộ phận và bổ sung. Nếu bạn có thể bắt đầu phân chia sớm, nó có thể có thể bị chồng chéo với phép cộng. CPU máy tính để bàn của bạn rất có thể có một đơn vị không theo thứ tự sẽ sắp xếp lại các câu lệnh để hưởng lợi từ sự chồng chéo đó. Hoặc nếu bạn có chương trình sau:

if (expr1)
    expr2;
else
    expr3;

Một CPU sắp xếp lại sẽ cố gắng tính toán ba biểu thức cùng một lúc và sau đó loại bỏ kết quả của một trong số chúng. Điều này làm cho nó nhanh hơn tổng thể. Nếu bạn có một số trình chặn trong chương trình của mình và bạn không thể sắp xếp lại, thì bạn đang sử dụng ít làn đường hơn trong CPU, nhưng nó có thể vẫn sẽ hiển thị 100%.

Sau đó, bạn có các tính năng SIMD trong CPU là các hoạt động véc tơ. Nó giống như GPGPU-light theo nghĩa là bạn thường chỉ có bốn hoặc tám thao tác cùng một lúc, GPU hoạt động như 32 hoặc 64. Tuy nhiên, bạn vẫn phải sử dụng điều đó để tạo ra FLOPS.

Những thứ như chia sẻ sai có thể dẫn đến chi phí đồng bộ hóa lớn thường xuất hiện dưới dạng tải kernel trong Linux. CPU được sử dụng hoàn toàn nhưng bạn không có nhiều thông lượng hữu ích.

Tôi đã thực hiện một số chương trình trên máy IBM Blue Gene / Q. Nó có nhiều cấp độ phân cấp ( sơ đồ của Blue Gene / L lỗi thời ) và do đó khó có thể lập trình hiệu quả. Bạn sẽ phải sử dụng hệ thống phân cấp đầy đủ xuống SIMD và SMT (Intel gọi đây là HyperThreading) để có được hiệu suất.

Và sau đó mạng thường giới hạn bạn. Do đó, nó chỉ ra rằng thời gian (đồng hồ treo tường) nhanh hơn để tính toán mọi thứ tại nhiều CPU cùng một lúc thay vì truyền thông qua mạng. Điều này sẽ đặt thêm tải cho CPU và làm cho chương trình chạy nhanh hơn. Nhưng thông lượng chương trình thực tế không tốt như có vẻ từ số nguyên.

Nếu bạn thêm GPU vào hỗn hợp, sẽ càng khó hơn khi phối hợp toàn bộ điều này để mang lại hiệu suất. Đó sẽ là một trong những điều tôi sẽ bắt đầu thực hiện trong Luận văn thạc sĩ QCD của tôi trong một vài tháng.


1

Bạn có thể quan tâm đến việc kiểm tra công cụ trình duyệt Servo đang được phát triển tại Mozilla Research, và cụ thể hơn là Web Render (video) của nó .

Mặc dù việc chuyển đổi một nhiệm vụ từ CPU sang GPU một cách linh hoạt có thể không thực tế, như đã đề cập trong các câu trả lời khác (đáng chú ý là @ Philip), việc nghiên cứu tải CPU / GPU trên các khối lượng công việc thông thường trước và chuyển một số nhiệm vụ sang tải ít hơn một.

Trong trường hợp Web Render, điều mới lạ là các trình duyệt truyền thống thực hiện hầu hết công việc kết xuất của chúng trên CPU (nghĩa là CPU được sử dụng để tính toán những đối tượng nào sẽ hiển thị, nơi cần cắt, v.v.). GPU thường tốt hơn ở nó ... ngoại trừ việc không phải tất cả các giai đoạn đều không quan trọng để thực hiện (loại bỏ một phần, đổ bóng, ... và văn bản).

Một phiên bản ban đầu của Web Render tỏ ra rất thành công trong việc tăng hiệu suất, nhưng không cố gắng giải quyết vấn đề kết xuất văn bản (và có một vài hạn chế khác). Mozilla Research hiện đang làm việc trên phiên bản thứ hai nhằm mục đích có ít hạn chế hơn và đáng chú ý là hỗ trợ kết xuất văn bản.

Tất nhiên, mục tiêu là giảm tải càng nhiều càng tốt cho quá trình kết xuất với GPU, để CPU tự do thực thi Javascript, cập nhật DOM và tất cả các tác vụ khác.

Vì vậy, mặc dù không cực đoan như đề xuất của bạn, nhưng nó đi vào hướng thiết kế một chiến lược tính toán với cả CPU và GPU.


0

Tập trung vào các trò chơi (vì bạn đã đề cập cụ thể trong bài đăng của mình), có một số cách bạn có thể cân bằng tải. Một ví dụ là "skinning", tức là tạo hình động cho một người mẫu. Đối với mỗi khung hình được hiển thị, bạn phải tạo ma trận biến đổi cho từng khung hình động và áp dụng nó cho các đỉnh của mô hình để chuyển đổi nó thành tư thế cần thiết. Bạn cũng phải nội suy các khung hình để có được chuyển động mượt mà , trừ khi bạn muốn hoạt hình của mình trông giống như Quake gốc (nghĩa là giật).

Trong tình huống này, bạn có thể thực hiện trên CPU và tải kết quả lên GPU để kết xuất hoặc thực hiện tính toán và kết xuất trên GPU. Tôi tin rằng ngày nay nó được thực hiện trên GPU (được gọi là "skin phần cứng"): thật hợp lý khi bạn có các phép tính tương đối đơn giản phải được thực hiện hàng ngàn lần và mỗi đỉnh có thể được tính đồng thời kể từ kết quả của đỉnh A không có ảnh hưởng đến kết quả của đỉnh B.

Tuy nhiên, về mặt lý thuyết, bạn có thể tự động chuyển đổi giữa việc thực hiện trên CPU hoặc GPU tùy thuộc vào mức độ quá tải của GPU và CPU.

Tuy nhiên, công cụ chặn chính để thực hiện điều này trên tất cả các tính toán là CPU và GPU có các điểm mạnh và điểm yếu khác nhau. Các công việc song song lớn được thực hiện tốt hơn trên GPU, trong khi các tác vụ tuyến tính chuyên sâu với phân nhánh được thực hiện tốt hơn trên CPU. Chỉ có một vài công việc thực tế có thể được thực hiện trên cả hai mà không có hiệu suất nghiêm trọng.

Nhìn chung, vấn đề chính với lập trình GPU (ít nhất là với OpenGL và DirectX 11 trở xuống) là bạn có ít quyền kiểm soát cách GPU diễn giải mã shader của bạn. Việc phân nhánh trong một shader rất rủi ro vì nếu bạn vô tình tạo ra sự phụ thuộc giữa các phép tính, thì GPU có thể quyết định bắt đầu hiển thị từng pixel của bạn, biến 60fps thành 10fps ngay lập tức mặc dù dữ liệu thực tế được hiển thị giống hệt nhau.


0

Một ví dụ trong thế giới thực là công cụ kết xuất LuxRender mã nguồn mở , có khả năng tải đầy đủ CPU và GPU cùng một lúc. Ngoài ra, nó có thể tải nhiều GPU cùng một lúc và cũng có thể phân phối trên nhiều máy tính.

LuxRender sử dụng OpenCL để tạo điều kiện thuận lợi cho việc này, mặc dù các bản dựng không có OpenCL cũng tồn tại.

Điều này là thực tế bởi vì các thuật toán mà LuxRender sử dụng rất song song. Thuật toán phổ biến nhất mà LuxRender sử dụng là theo dõi đường dẫn , trong đó nhiều đường ánh sáng riêng lẻ có thể được tính toán độc lập với nhau, một tình huống lý tưởng cho điện toán GPU và không yêu cầu đồng bộ hóa phức tạp giữa các nút tính toán. Tuy nhiên, các hạn chế của GPU (dung lượng bộ nhớ thấp hơn, thiếu hỗ trợ cho một số tính năng kết xuất phức tạp và thiếu tính khả dụng chung đối với một số nghệ sĩ) đảm bảo rằng hỗ trợ CPU vẫn là điều cần thiết.


điểm hiển thị hình ảnh này là gì, nó liên quan đến câu hỏi như thế nào?
gnat

1
Ừ được rồi Tôi sẽ xóa nó. Tôi đã nghĩ rằng nó sẽ dễ dàng chứng minh nó là loại phần mềm nào. Nhưng có lẽ nó thực sự gây mất tập trung. (Có nhiều loại công cụ kết xuất khác nhau; công cụ này được nhắm mục tiêu vào ảnh tĩnh quang học.)
PythonNut

0

Vâng, nó chắc chắn có thể.

Bất kỳ tính toán nào mà CPU có thể làm, GPU cũng có thể thực hiện và ngược lại.

Nhưng nó không phổ biến vì:

  • Độ phức tạp kỹ thuật Mặc dù có thể chạy cùng một mã trên CPU và GPU (ví dụ CUDA), bộ xử lý có các khả năng và đặc tính hiệu suất khác nhau. Một là MIMD; khác, SIMD. Cái gì nhanh thì cái kia chậm (ví dụ như phân nhánh), vì vậy bạn cần phải viết mã riêng để tối đa hóa hiệu suất.

  • GPU hiệu quả về chi phí được tổng hợp mạnh hơn rất nhiều so với CPU. Toàn bộ ý tưởng của GPU là sử dụng các bộ xử lý rẻ hơn, chậm hơn, nhưng nhiều bộ xử lý hơn để thực hiện các tính toán nhanh hơn nhiều so với CPU có thể có cùng chi phí. GPU có hiệu quả hơn về chi phí với một hoặc hai đơn đặt hàng lớn.

Nếu bạn có được thuật toán của mình để chạy trên GPU, điều đó có ý nghĩa hơn để tối ưu hóa cho những thứ đó và thêm bao nhiêu tùy ý.

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.