- vừa được xem lúc

[NVIDIA Tools] Bài 7:Warp Scheduler

0 0 11

Người đăng: CisMine

Theo Viblo Asia

Ở trong bài Synchronization - Asynchronization mình có nhắc đến khái niệm latency hiding, một khái niệm rất thường thấy khi nhắc về cuda và khi nói đến latency hiding là sẽ nói đến always keep thread busy, vậy nên ở bài viết này mình sẽ giải thích rõ hơn về khái niệm này cũng như cơ chế hoạt động của nó - có thể nói không thể thiếu cơ chế này vì nó giúp ích chúng ta rất nhiều trong việc tối ưu code

Bài viết này mục đích là giúp các bạn hiểu rõ hơn về cơ chế hoạt động của cuda vậy nên sẽ khá quan trọng trong series NVIDIA Tools nhưng nếu bạn chỉ quan tâm đến việc code cuda ở mức độ cơ bản thì các bạn có thể bỏ qua bài viết này

Warp Scheduler

Trước khi vào bài học thì mình sẽ lấy ví dụ để các bạn dễ hình dung hơn:

Giả sử có 100 người tới bưu điện để gửi hàng và chỉ có 1 người làm việc, và để gửi hàng thành công bạn phải thực hiện 2 bước: điền đơn thông tin gửi hàng ( tốn nhiều thời gian ) - nhân viên xác nhận đơn và thực hiện thủ tục gửi hàng ( khá nhanh ). Ở đây người nhân viên thay vì cứ đợi từng người điền đơn xong để làm thủ tục thì tới lượt người nào sẽ được phát đơn và ra chỗ khác điền, và khi điền xong quay lại hàng chờ ==> nhanh hơn rất nhiều so với việc đợi từng người 1 điền đơn xong.

Ở đây máy tính cũng vậy, giả sử ta có bài toán: y[i] += x[i] * 3 thì máy tính cũng phải thực hiện 2 bước:

  • Memory instruction: time between load/store operation being issue and data arriving at its destination
  • Arithmetic instruction: time an arithmetic operation start to its output

Ở đây mình xin phép dùng tiếng anh nhưng các bạn có thể hiểu đơn giản là cũng cần 2 quy trình: đầu tiên là load/store data lên memory mà mình muốn xử lí ( khá lâu ) tiếp đến là tính toán cho tới khi ra được output

Quay lại ví dụ y[i] += x[i] * 3 , thay vì máy tính phải đợi load/store x[0] và y[0] thì máy tính sẽ chuyển qua load/store x[1] và y[1] rồi cứ tiếp tục cho đến khi x[0] và y[0] load/store xong mới quay về để tính toán

Cách 1

warpS.jpeg

Cách 2

warpS2.jpeg

Tóm lại Warp Scheduler sẽ thực hiện hành động swap các warp đang bận để tiết kiệm thời gian nên người ta hay gọi là latency hiding hoặc always keep threads busy ( tùy vào mỗi máy mà 1 Warp Scheduler có thể điều khiển 1 số lượng warp nhất định )

Nếu các bạn thấy ví dụ trên giống với ví dụ phát bánh kẹo ở bài Cách thức hoạt động của máy tính thì các bạn đúng rồi đó

Khi nói đến warp chúng ta sẽ luôn thấy 3 trạng thái của warp:

  • stalled: warp đang bận thực thi 1 thứ gì đó
  • eligible: warp đang rãnh và sẵn sàng tham gia
  • selected: warp được chọn để thực thi

Có thể hiểu là warp sau khi được selected thì sẽ vô thực thi Memory instruction và trong thời gian đợi thì sẽ được swap qua warp khác, ở đây sẽ có 2 tình huống là warp tiếp đó stalled hoặc eligible, nếu eligible thì sẽ tuyệt vời còn nếu là stalled thì sẽ được swap tiếp cho đến khi gặp được warp eligible

Câu hỏi đặt ra: Nếu vậy chúng ta chỉ cần tạo ra nhiều warp thì số lượng eligible sẽ tăng lên ?

Nếu bạn cũng nghĩ như vậy thì sai nha, tạo ra nhiều warp đồng nghĩa với việc warp scheduler sẽ thực hiện nhiều hơn và khi tạo ra nhiều warp ( tức là nhiều thread ) dẫn tới số lượng register của mỗi thread ít đi ==> khiến SM chạy chậm ==> chúng ta phải cân nhắc đến việc sử dụng bao nhiêu thread thì phù hợp ?

Nếu các bạn nghĩ có 128 người tới gửi thư thì chúng ta sẽ dùng 128 người nhân viên thì sai nha, cũng giống như nếu chúng ta cần xử lí 1 array 128 phần tử mà dùng 128 thread ( 4 warp ) là sai lầm

Lý do: tốn tài nguyên và ngày nay máy tính chúng ta rất rất mạnh, tức là 1 nhân viên có thể cùng 1 lúc xử lí cho 2 người mà chúng ta chỉ cho họ xử lí 1 người tại 1 thời điểm thì hơi phí ==> 1 thread xử lí 2 phần tử ===> giảm số lượng thread khởi tạo ==> tăng register cho mỗi thread + giảm bớt công việc cho warp scheduler

Cũng vì lý do đó mà khi các bạn profile các đoạn code opencv cuda bằng nsight system sẽ thấy họ dùng rất ít thread

Câu hỏi đặt ra: vậy chúng ta dùng bao nhiêu thread là phù hợp?

==> Tùy thuộc vào cấu hình của mỗi máy tính cũng như những nguyên nhân khiến warp stalled mà chúng ta lựa chọn, ở bài sau mình sẽ phân tích những nguyên nhân khiến warp stalled cũng như cách xác định số lượng thread phù hợp

Bình luận

Bài viết tương tự

- vừa được xem lúc

GPU programming với Golang

GPU programming với Golang. Ở bài trước mình có giới thiệu về kĩ thuật lập trình GPU với OpenCL bằng C/C++.

0 0 27

- vừa được xem lúc

Allocating Memory on HPC ( Slurm Scripts)

Bài viết này giải thích cách yêu cầu bộ nhớ trong các Slurm Scripts và cách xử lý các lỗi thường gặp liên quan đến bộ nhớ CPU và GPU. Lưu ý rằng "memory" luôn đề cập đến RAM .

0 0 27

- vừa được xem lúc

[Lập trình song song] Bài 1: Giới thiệu về CPU-GPU

Trước khi tìm hiểu thế nào là lập trình song song cũng như cách code thì mình phải biết 1 chút về lịch sử hình thành nên ở bài 1 mình sẽ giới thiệu sơ lược những điều bạn nên biết ở lĩnh vực này. Chắc

0 0 28

- vừa được xem lúc

[Lập trình song song] Bài 2: Cài đặt môi trường code CudaC

Trước khi code thì chúng ta phải setup môi trường để code thì ở bài này mình sẽ hướng dẫn các bạn cách setup và đối với những ai sở hữu máy tính mà không có GPU thì cũng đừng có lo vì chúng ta sẽ code

0 0 18

- vừa được xem lúc

[Lập trình song song] Bài bonus 1: Cách thức hoạt động của máy tính

Ở bài này mình sẽ nói qua về cách máy tính hoạt động trong việc lấy và xử lí data qua ví dụ cực kì trực quan và dễ hiểu . Và xin lưu ý là ví dụ này sẽ được nhắc lại khá nhiều trong các bài học về lập

0 0 19

- vừa được xem lúc

[Lập trình song song] Bài bonus 2: Các thuật ngữ trong lập trình song song

Ở bài này mình sẽ giải thích các thuật ngữ thường hay được đề cập tới trong lập trình song song. .

0 0 23