Làm thế nào để CUDA khối / warps / chủ đề ánh xạ vào lõi CUDA?


142

Tôi đã sử dụng CUDA được vài tuần, nhưng tôi có một số nghi ngờ về việc phân bổ các khối / sợi dọc / luồng. Tôi đang nghiên cứu kiến ​​trúc từ quan điểm giáo khoa (dự án đại học), vì vậy đạt được hiệu suất cao nhất không phải là mối quan tâm của tôi.

Trước hết, tôi muốn hiểu nếu tôi nói thẳng những điều này:

  1. Lập trình viên viết một kernel và tổ chức thực hiện nó trong một lưới các khối luồng.

  2. Mỗi khối được gán cho Bộ đa xử lý phát trực tuyến (SM). Sau khi được chỉ định, nó không thể di chuyển sang SM khác.

  3. Mỗi SM chia các khối riêng của mình thành Warps (hiện có kích thước tối đa là 32 luồng). Tất cả các luồng trong một sợi dọc thực thi đồng thời trên các tài nguyên của SM.

  4. Việc thực thi thực tế của một luồng được thực hiện bởi các lõi CUDA có trong SM. Không có ánh xạ cụ thể giữa các luồng và lõi.

  5. Nếu một sợi dọc chứa 20 luồng, nhưng hiện tại chỉ có 16 lõi có sẵn, sợi dọc sẽ không chạy.

  6. Mặt khác, nếu một khối chứa 48 luồng, nó sẽ được chia thành 2 sợi dọc và chúng sẽ thực thi song song với điều kiện là có đủ bộ nhớ.

  7. Nếu một luồng bắt đầu trên một lõi, thì nó bị đình trệ để truy cập bộ nhớ hoặc cho một hoạt động điểm nổi dài, việc thực thi của nó có thể tiếp tục trên một lõi khác.

Họ có đúng không?

Bây giờ, tôi có GeForce 560 Ti nên theo thông số kỹ thuật, nó được trang bị 8 SM, mỗi lõi chứa 48 lõi CUDA (tổng cộng 384 lõi).

Mục tiêu của tôi là đảm bảo rằng mọi lõi của kiến ​​trúc đều thực hiện các hướng dẫn CÙNG. Giả sử rằng mã của tôi sẽ không yêu cầu đăng ký nhiều hơn mã có sẵn trong mỗi SM, tôi tưởng tượng các cách tiếp cận khác nhau:

  1. Tôi tạo 8 khối gồm 48 luồng mỗi luồng, để mỗi SM có 1 khối để thực thi. Trong trường hợp này, 48 luồng sẽ thực thi song song trong SM (khai thác tất cả 48 lõi có sẵn cho chúng)?

  2. Có sự khác biệt nào không nếu tôi khởi chạy 64 khối 6 luồng? (Giả sử rằng họ sẽ được ánh xạ đồng đều giữa các SM)

  3. Nếu tôi "nhấn chìm" GPU trong công việc được lên lịch (ví dụ, tạo ra 1024 khối của mỗi luồng 1024) thì có lý khi cho rằng tất cả các lõi sẽ được sử dụng tại một điểm nhất định và sẽ thực hiện các phép tính tương tự (giả sử rằng các luồng không bao giờ bị đình trệ)?

  4. Có cách nào để kiểm tra các tình huống này bằng cách sử dụng hồ sơ không?

  5. Có bất kỳ tài liệu tham khảo cho công cụ này? Tôi đọc hướng dẫn lập trình CUDA và các chương dành riêng cho kiến ​​trúc phần cứng trong "Lập trình bộ xử lý song song lớn" và "Thiết kế và phát triển ứng dụng CUDA"; nhưng tôi không thể có được một câu trả lời chính xác.


Tôi muốn thêm vào như một bình luận "lõi CUDA" là gì. "Lõi CUDA" hoặc "Đơn vị thực thi" là ALU và FPU số nguyên được đường ống đầy đủ thực thi một lệnh hướng dẫn số học trên mỗi chu kỳ đồng hồ trong một luồng cuda.
bruziuz

Câu trả lời:


123

Hai trong số các tài liệu tham khảo tốt nhất là

  1. NVIDIA Fermi Compute Architecture Whitepaper
  2. Nhận xét về GF104

Tôi sẽ cố gắng trả lời từng câu hỏi của bạn.

Lập trình viên phân chia công việc thành các luồng, luồng thành các khối luồng và khối luồng thành lưới. Nhà phân phối công việc tính toán phân bổ các khối luồng cho Bộ đa xử lý phát trực tuyến (SM). Khi một khối luồng được phân phối cho SM, các tài nguyên cho khối luồng được phân bổ (sợi dọc và bộ nhớ dùng chung) và các luồng được chia thành các nhóm gồm 32 luồng được gọi là sợi dọc. Khi một sợi dọc được phân bổ, nó được gọi là một sợi dọc hoạt động. Hai bộ lập lịch warp chọn hai warp hoạt động trên mỗi chu kỳ và gửi warp đến các đơn vị thực thi. Để biết thêm chi tiết về các đơn vị thực hiện và công văn hướng dẫn, xem 1 p.7-10 và 2 .

4 ' . Có một ánh xạ giữa laneid (chỉ số luồng trong một sợi dọc) và lõi.

5 ' . Nếu một sợi dọc chứa ít hơn 32 luồng thì trong hầu hết các trường hợp, nó sẽ được thực hiện giống như khi nó có 32 luồng. Warps có thể có ít hơn 32 luồng hoạt động vì nhiều lý do: số luồng trên mỗi khối không chia hết cho 32, chương trình thực thi một khối phân kỳ để các luồng không đi theo đường dẫn hiện tại được đánh dấu không hoạt động hoặc một luồng trong sợi dọc đã thoát.

6 ' . Một khối luồng sẽ được chia thành WarpsPerBlock = (ThemesPerBlock + WarpSize - 1) / WarpSize Không có yêu cầu nào đối với bộ lập lịch warp để chọn hai sợi dọc từ cùng một khối luồng.

7 ' . Một đơn vị thực thi sẽ không bị đình trệ trong một hoạt động bộ nhớ. Nếu tài nguyên không có sẵn khi một lệnh sẵn sàng được gửi đi, lệnh sẽ được gửi lại trong tương lai khi tài nguyên có sẵn. Warp có thể bị đình trệ tại các rào cản, trên các hoạt động bộ nhớ, hoạt động kết cấu, phụ thuộc dữ liệu, ... Một sợi dọc bị đình trệ không đủ điều kiện để được chọn bởi bộ lập lịch warp. Trên Fermi, rất hữu ích khi có ít nhất 2 warp đủ điều kiện cho mỗi chu kỳ để bộ lập lịch warp có thể đưa ra một hướng dẫn.

Xem tài liệu tham khảo 2 để biết sự khác biệt giữa GTX480 và GTX560.

Nếu bạn đọc tài liệu tham khảo (vài phút) tôi nghĩ bạn sẽ thấy rằng mục tiêu của bạn không có ý nghĩa. Tôi sẽ cố gắng đáp ứng quan điểm của bạn.

1 ' . Nếu bạn khởi chạy kernel <<< 8, 48 >>> bạn sẽ nhận được 8 khối mỗi khối với 2 sợi dọc gồm 32 và 16 luồng. Không có gì đảm bảo rằng 8 khối này sẽ được gán cho các SM khác nhau. Nếu 2 khối được phân bổ cho SM thì có thể mỗi bộ lập lịch dọc có thể chọn một sợi dọc và thực hiện sợi dọc. Bạn sẽ chỉ sử dụng 32 trong số 48 lõi.

2 ' . Có một sự khác biệt lớn giữa 8 khối 48 luồng và 64 khối 6 luồng. Giả sử rằng hạt nhân của bạn không có phân kỳ và mỗi luồng thực hiện 10 hướng dẫn.

  • 8 khối với 48 luồng = 16 warps * 10 hướng dẫn = 160 hướng dẫn
  • 64 khối với 6 luồng = 64 warps * 10 hướng dẫn = 640 hướng dẫn

Để có được hiệu quả tối ưu, việc phân chia công việc phải theo bội số của 32 luồng. Phần cứng sẽ không kết hợp các luồng từ các sợi dọc khác nhau.

3 ' . Một GTX560 có thể có 8 khối SM * 8 khối = 64 khối cùng một lúc hoặc 8 SM * 48 warps = 512 warps nếu hạt nhân không tối đa đăng ký hoặc bộ nhớ chia sẻ. Tại bất kỳ thời điểm nào, một phần công việc sẽ hoạt động trên SM. Mỗi SM có nhiều đơn vị thực thi (nhiều hơn lõi CUDA). Những tài nguyên nào đang được sử dụng tại bất kỳ thời điểm nào đều phụ thuộc vào bộ lập lịch dọc và hỗn hợp hướng dẫn của ứng dụng. Nếu bạn không thực hiện các hoạt động TEX thì các đơn vị TEX sẽ không hoạt động. Nếu bạn không thực hiện thao tác điểm nổi đặc biệt, các đơn vị SUFU sẽ không hoạt động.

4 ' . Parallel Nsight và chương trình Visual Profiler

a. thực hiện IPC

b. cấp IPC

c. cong vênh hoạt động trên mỗi chu kỳ hoạt động

d. warp đủ điều kiện cho mỗi chu kỳ hoạt động (chỉ Nsight)

e. lý do gian hàng warp (chỉ Nsight)

f. chủ đề hoạt động trên mỗi lệnh được thực hiện

Trình lược tả không hiển thị phần trăm sử dụng của bất kỳ đơn vị thực thi nào. Đối với GTX560, ước tính sơ bộ sẽ là IssuedIPC / MaxIPC. Đối với MaxIPC giả sử GF100 (GTX480) là 2 GF10x (GTX560) là 4 nhưng mục tiêu là 3 là mục tiêu tốt hơn.


1
Cảm ơn bạn vì câu trả lời. Tôi đọc các tài liệu tham khảo, nhưng có một vài điều mà tôi không hiểu trong câu trả lời của bạn. Trong các câu hỏi sau đây, tôi giả sử rằng chúng ta đang sử dụng kiến ​​trúc Fermi với 48 lõi (16 lõi * 3 "nhóm lõi"): 1. Bạn đã đề cập đến ánh xạ giữa lõi và làn đường. Đó là loại bản đồ gì? 2. Từ các tài liệu tham khảo tôi nhận được rằng mỗi "nhóm cốt lõi" thực hiện tối đa một nửa sợi dọc (16 luồng) trên mỗi chu kỳ đồng hồ. Vì vậy, theo lý thuyết, nếu chúng ta có 48 luồng trong cùng một khối, chúng sẽ được tổ chức thành 3 nửa sợi dọc và thực hiện song song trên 48 lõi. Tôi có đúng không
Daedalus

1
Các lõi CUDA là số đơn vị FP chính xác duy nhất. Suy nghĩ về việc thực hiện theo các lõi CUDA là không chính xác. Mỗi sợi dọc có 32 luồng. Các luồng này sẽ được cấp cho một nhóm các đơn vị thực thi (ví dụ 16 lõi cuda). Để phát hành cho tất cả 48 lõi trong một đồng hồ, một trong hai bộ lập lịch dọc cần chọn một sợi dọc đáp ứng yêu cầu của một cặp siêu thanh và cả hai hướng dẫn cần phải được thực hiện bởi các lõi CUDA. Ngoài ra, bộ lập lịch warp khác phải chọn một sợi dọc có lệnh tiếp theo sẽ được thực thi bởi các lõi CUDA.
Greg Smith

1
Không có yêu cầu rằng các sợi dọc trong cùng một khối hoặc các sợi dọc trong một khối có cùng bộ đếm chương trình.
Greg Smith

2
Trong ví dụ của bạn, mỗi trình lập lịch biểu sẽ chọn một lệnh dọc và đưa ra 1 lệnh. Trong trường hợp này, chỉ có 2 nhóm đơn vị thực hiện sẽ được sử dụng. Để sử dụng nhiều đơn vị thực thi hơn 1 trong số các bộ lập lịch phải phát hành kép. Như đã chỉ ra trong các tài liệu tham khảo, có nhiều loại đơn vị thực thi (không chỉ các lõi cuda được đặt) và có các quy tắc ghép nối lệnh (không được ghi chép tốt) phải được đáp ứng cho các trình lập lịch biểu cho vấn đề kép.
Greg Smith

1
@GregSmith Tôi đang tìm kiếm trên tất cả các trang web để tìm ra 8 khối hoạt động trên mỗi SM trong kiến ​​trúc Fermi đến từ đâu. Nó thậm chí không được đề cập trong whitepaper fermi. Bạn có bất cứ tài liệu tham khảo thêm về điều đó?
Greg K.

8

"E. Nếu một sợi dọc chứa 20 luồng, nhưng hiện tại chỉ có 16 lõi có sẵn, sợi dọc sẽ không chạy."

không chính xác Bạn đang nhầm lẫn các lõi theo nghĩa thông thường của chúng (cũng được sử dụng trong CPU) - số lượng "đa bộ xử lý" trong GPU, với các lõi trong tiếp thị nVIDIA ("thẻ của chúng tôi có hàng ngàn lõi CUDA").

Bản thân một sợi dọc chỉ có thể được lên lịch trên một lõi đơn (= bộ đa xử lý) và có thể chạy tới 32 luồng cùng lúc; nó không thể sử dụng nhiều hơn một lõi.

Số "48 sợi dọc" là số lượng sợi dọc hoạt động tối đa (sợi dọc có thể được chọn để lên lịch làm việc trong chu kỳ tiếp theo, ở bất kỳ chu kỳ nhất định) trên mỗi bộ xử lý đa năng, trên GPU nVIDIA có Khả năng tính toán 2.x; và con số này tương ứng với 1536 = 48 x 32 chủ đề.

Trả lời dựa trên hội thảo trực tuyến này


@GregSmith: Đã chỉnh sửa câu trả lời để giải quyết vấn đề này. Thật tốt khi bạn kiên nhẫn với nó, nhưng - đã năm năm rồi ...
einpoklum

lõi đơn (= đa bộ xử lý)? Tôi nghĩ rằng câu hỏi giả định thuật ngữ đơn lõi = bộ xử lý và không phải là bộ đa xử lý. Với thuật ngữ của bạn, câu trả lời của bạn là chính xác.
Adarsh
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.