Phổ biến kiến thức: GPU hoạt động như thế nào?

Xin chào các bạn, hôm nay chúng ta sẽ nói chi tiết về cách hoạt động của GPU.

Với sự phát triển nhanh chóng của AI và AI PC, bộ phận xử lý đồ họa GPU đã trở thành động lực chính thúc đẩy sự phát triển khoa học trong các lĩnh vực nghiên cứu như thiên văn học và vật lý. AI được tăng tốc bởi GPU đang giúp các nhà khoa học giải quyết các vấn đề phức tạp chưa từng có.

So với CPU, GPU được thiết kế để xử lý số lượng lớn các tác vụ song song, giúp chúng thực hiện các tác vụ tính toán chuyên sâu tốt hơn. Hôm nay chúng ta sẽ nói về lý do tại sao GPU lại hiệu quả hơn trong tính toán song song từ cơ chế hoạt động và nguyên lý thiết kế của GPU.

1716719152067.png

Ba thành phần của bộ xử lý

Chúng ta biết rằng bất kỳ bộ xử lý nào cũng bao gồm ba phần bên trong, đó là đơn vị logic số học (ALU), đơn vị điều khiển và bộ đệm. Nhưng CPU (Bộ xử lý trung tâm) và GPU ( Bộ xử lý đồ họa) là hai loại bộ xử lý máy tính khác nhau.

1716719197881.png
Nói một cách đơn giản, CPU xử lý từng tác vụ một tốt hơn, trong khi GPU có thể xử lý nhiều tác vụ cùng lúc. Điều này là do CPU được tối ưu hóa cho độ trễ, trong khi GPU được tối ưu hóa cho băng thông. Giống như một số người giỏi thực hiện từng nhiệm vụ một theo trình tự, một số người có thể thực hiện nhiều nhiệm vụ cùng một lúc.

Tôi sẽ giải thích sự khác biệt giữa hai điều này một cách đơn giản bằng cách sử dụng một phép loại suy. CPU giống như một chiếc xe đua mô tô, còn GPU giống như một chiếc xe buýt nếu nhiệm vụ của cả hai là đưa một người từ vị trí A đến vị trí B thì CPU (xe máy) chắc chắn sẽ đến nơi nhanh hơn, nhưng nếu 100 người thì như vậy. được gửi từ vị trí A đến vị trí B thì GPU (xe buýt) sẽ mất ít thời gian hơn để vận chuyển 100 người vì nó có thể vận chuyển nhiều người hơn cùng một lúc.

1716719230083.png

Nói cách khác, CPU thực hiện tác vụ nhanh hơn trong một lần thực thi, nhưng lợi thế của GPU trở nên quan trọng hơn khi yêu cầu khối lượng công việc lặp đi lặp lại lớn (ví dụ: các phép toán ma trận: (A*B)*C). Do đó, mặc dù thời gian phân phối đơn của CPU nhanh hơn nhưng lợi thế của GPU lại đáng kể hơn khi xử lý xử lý hình ảnh, kết xuất hoạt ảnh và học sâu đòi hỏi khối lượng công việc lặp đi lặp lại lớn.

Tóm lại, CPU là bậc thầy về nhiều khả năng tính toán khác nhau. Ưu điểm của nó bao gồm khả năng lập kế hoạch, quản lý và phối hợp mạnh mẽ và có thể thực hiện các hoạt động logic phức tạp. Tuy nhiên, do số lượng đơn vị tính toán và lõi nhỏ nên nó chỉ phù hợp với số lượng hoạt động tương đối nhỏ. GPU không thể hoạt động một mình. Nó tương đương với một nhóm lớn nhân viên đường ống chấp nhận lập lịch CPU và phù hợp để thực hiện một số lượng lớn các thao tác đơn giản. CPU và GPU có những thế mạnh chức năng riêng và bổ sung cho nhau để đạt được hiệu năng tính toán tốt nhất.Vậy điều gì khiến CPU và GPU hoạt động khác nhau? Điều đó còn phụ thuộc vào ý tưởng thiết kế của cả hai.

FLOPS không phải là vấn đề cốt lõi?

Các phép tính dấu phẩy động mỗi giây (FLOPS) dựa trên số phép tính số học dấu phẩy động mà bộ xử lý có thể thực hiện trong một giây và thường được sử dụng để đo hiệu suất máy tính. Mặc dù mọi người thường hỏi FLOPS của một thiết bị là gì nhưng đây thực sự không phải là câu hỏi cốt lõi.

1716719284015.png

Chúng ta có thể nói cách khác, đó là mặc dù một số chuyên gia hoặc thuật toán cụ thể sẽ đặc biệt chú ý đến FLOPS. Nhưng FLOPS thực ra không phải là tâm điểm quan tâm của công chúng.

1716719314128.png

Tại sao lại nói vậy? Lấy hình trên làm ví dụ, chúng ta hãy xem CPU đang hoạt động: CPU có thể thực hiện các hoạt động ở khoảng 2000 GFLOPs FP64, nhưng bộ nhớ chỉ có thể cung cấp dữ liệu cho CPU ở tốc độ 200 GB/s, đây là giới hạn của bộ xử lý hiện đại. Vì vậy, khi CPU muốn xử lý 2 nghìn tỷ giá trị có độ chính xác kép mỗi giây, bộ nhớ chỉ có thể cung cấp 25 tỷ mỗi giây. Lúc này, sẽ có sự mất cân bằng về “cường độ tính toán” của thiết bị. Lúc này, nó phụ thuộc vào việc thiết bị CPU cần nỗ lực đến mức nào để bù đắp cho việc thiếu dữ liệu do bộ nhớ cung cấp. Nếu không, bộ xử lý sẽ lãng phí thời gian không hoạt động và rơi vào chế độ được gọi là "giới hạn băng thông bộ nhớ".

Trên thực tế, ít nhất 3/4 hoặc nhiều hơn tất cả các chương trình thực sự bị giới hạn bởi băng thông bộ nhớ vì rất ít thuật toán có thể hoàn thành đủ các thao tác trên mỗi lần tải dữ liệu để tận dụng tối đa hiệu suất phần cứng. Lúc này có thể sẽ thích hợp hơn nếu mua CPU rẻ hơn.

Yêu cầu cường độ tính toán cao này khó đạt được đối với hầu hết các thuật toán. Trên thực tế, chỉ có những thuật toán đặc biệt như phép nhân ma trận mới đáp ứng được yêu cầu này. Tiếp theo, chúng ta hãy xem GPU có thể bù đắp cường độ tính toán này như thế nào.

1716719376765.png

Thông qua bảng trên, chúng tôi so sánh hiệu suất của một số quy trình khác nhau trên GPU và CPU. Bạn sẽ thấy rằng mặc dù chip NVIDIA có FLOPS cao hơn nhưng cường độ tính toán của chúng gần như giống nhau. Điều này là do NVIDIA được trang bị bộ nhớ băng thông cao hơn để duy trì sự cân bằng.

Trên thực tế, mỗi thế hệ GPU có xu hướng tăng FLOPS nhanh hơn tốc độ tăng băng thông bộ nhớ. Điều này dẫn đến cường độ tính toán ngày càng tăng và đặt ra những thách thức lớn hơn cho việc lập trình thuật toán. Điều này đòi hỏi GPU phải liên tục làm việc chăm chỉ để tối ưu hóa các thuật toán nhằm đảm bảo những con chip mạnh mẽ này có thể duy trì hoạt động hiệu quả. Bởi vì rất ít thuật toán có thể hoàn thành đủ các thao tác trên mỗi lần tải dữ liệu để tận dụng tối đa hiệu suất phần cứng.Tất nhiên, hỗ trợ bộ nhớ cao và tối ưu hóa mã không phải là tất cả những lợi thế về hiệu suất của GPU, chúng ta cũng cần xem xét độ trễ. Hãy nói nhiều hơn về khái niệm độ trễ. Tại sao độ trễ rất quan trọng?

Tại sao độ trễ lại quan trọng đến vậy?

Độ trễ, chúng ta hãy hiểu bằng trực giác thông qua dòng thời gian. Đánh giá từ thao tác cơ bản nhất: ax + y. Đầu tiên, biến x được tải. Tiếp theo, tải y. Bởi vì phép toán là a nhân x cộng y. Do đó, yêu cầu tải y sẽ được bắt đầu cùng lúc. Sau đó, sẽ có một khoảng thời gian chờ đợi đáng kể cho đến khi dữ liệu của x được trả về. Khoảng thời gian này thường không hoạt động, chúng ta gọi là độ trễ, dẫn đến việc tính toán rất kém hiệu quả.

1716719452606.png
Mặc dù thời gian này ngắn nhưng nó có thể bị che lấp bởi công việc tính toán hữu ích khác và sẽ không gây ra sự chậm trễ đáng kể. Nhưng trình biên dịch bộ xử lý thực sự dành rất nhiều nỗ lực vào việc tối ưu hóa đường ống để đảm bảo rằng việc tải dữ liệu được bắt đầu càng sớm càng tốt để có thể thực hiện các hoạt động tính toán khác. Đường ống này là chìa khóa để tối ưu hóa hiệu suất trong hầu hết các chương trình vì độ trễ truy cập bộ nhớ thường lớn hơn nhiều so với độ trễ tính toán.

1716719493572.png

Vậy tại sao điều này xảy ra? Điều này là do ánh sáng chỉ có thể truyền đi một quãng đường ngắn trong một chu kỳ đồng hồ. Với kích thước của chip, có thể mất một hoặc nhiều chu kỳ xung nhịp để tín hiệu điện truyền từ bên này sang bên kia của chip. Vì vậy, các định luật vật lý trở thành yếu tố then chốt hạn chế hiệu suất. Đặc biệt khi dữ liệu cần được lấy từ bộ nhớ, việc truyền dữ liệu khứ hồi có thể cần 10 đến 20 chu kỳ xung nhịp.

1716719527849.png

Độ trễ có nghĩa là mất nhiều thời gian để chờ dữ liệu đến.

Như đã đề cập trước đó, CPU thường không hoạt động vì độ trễ của bộ nhớ khiến nó không thể hoạt động liên tục. Mặc dù CPU có rất nhiều sức mạnh tính toán (tức là FLOPS), tôi muốn bộ nhớ phù hợp với nó và đảm bảo dữ liệu đến kịp thời.

1716719566048.png

Lấy Xeon 8280 làm ví dụ. CPU này có bộ nhớ 131GB và độ trễ 89 nano giây. Khi băng thông bộ nhớ là 131GB/s, chỉ có thể di chuyển khoảng 11.659 byte dữ liệu trong chu kỳ trễ bộ nhớ. Điều này có vẻ không tệ, nhưng khi chúng ta xem xét rằng thao tác DAXPY chỉ tải hai giá trị 8 byte (tức là x và y), tổng cộng chỉ có 16 byte, hiệu suất trở nên rất thấp, chỉ 0,14%. Đây rõ ràng không phải là một kết quả tốt. Ngay cả với bộ nhớ băng thông cao có sẵn để xử lý cường độ tính toán, nó hầu như không có lợi thế gì. Một chi phí rất lớn đã được trả cho CPU và bộ nhớ hiệu suất cao, nhưng kết quả không lý tưởng.

1716719609485.png

Điều này là do chương trình bị ảnh hưởng bởi liên kết lười, một dạng hạn chế bộ nhớ phổ biến xảy ra thường xuyên hơn chúng ta nghĩ. Điều này cũng giải thích tại sao tôi không quan tâm nhiều đến FLOPS, vì ngay cả khi băng thông bộ nhớ không thể được sử dụng hết thì bộ phận tính toán cũng không thể bận được. Nếu tôi chia 11659 byte dữ liệu cho 16 byte (tức là tổng số byte mà thao tác DAXPY yêu cầu để tải x và y), tôi thấy rằng 729 lần lặp DAXPY cần được thực thi đồng thời để có được số tiền chi tiêu cho giá trị bộ nhớ. Vì vậy, đối mặt với hiệu quả bộ nhớ thấp này, 729 thao tác cần được xử lý đồng thời.

1716719649136.png

Tại thời điểm này, sự đồng thời là cần thiết để giải quyết vấn đề này. Đồng thời, như tên cho thấy, đang thực hiện nhiều việc cùng một lúc. Tuy nhiên, lưu ý rằng các hoạt động này không nhất thiết phải thực hiện đồng thời, chúng chỉ cần có khả năng tiến hành độc lập. Trình biên dịch GPU có một phương pháp tối ưu hóa được gọi là giải mã vòng lặp, có thể xác định các phần có thể được thực thi độc lập và phát hành chúng liên tục để cải thiện hiệu quả thực thi.
Tuy nhiên, phương pháp tối ưu hóa được thực hiện trong vòng lặp thực tế bị giới hạn bởi số lượng thao tác mà phần cứng có thể theo dõi đồng thời, khiến nó gần như không thể hoàn thành. Trong đường ống phần cứng, nó chỉ có thể xử lý một số lượng giao dịch giới hạn cùng một lúc. Nếu vượt quá con số này, nó phải đợi giao dịch trước đó hoàn tất. Vì vậy, việc hủy kiểm soát vòng lặp có lợi về mặt làm cho đường ống trở nên dày hơn, nhưng rõ ràng là nó cũng bị hạn chế bởi nhiều yếu tố khác trong kiến trúc máy.

1716719688168.png

Tại thời điểm này, bạn cần xem xét số lượng luồng tối đa mà phần cứng có thể hỗ trợ, điều đó có nghĩa là nhiều thao tác thực sự diễn ra đồng thời. GPU thực hiện tốt công việc hỗ trợ này.

Các luồng có vai trò gì trong GPU?

Một điểm khác biệt rất đáng chú ý giữa GPU và CPU là yêu cầu về độ trễ và băng thông của GPU cao hơn nhiều so với CPU, điều đó có nghĩa là nó cần số luồng gấp khoảng 40 lần để bù đắp cho độ trễ này. Nhưng trên thực tế, GPU có số luồng nhiều hơn 100 lần so với các loại bộ xử lý khác. Do đó, trong các ứng dụng thực tế, hiệu suất GPU thực sự tốt hơn.

Trên thực tế, số lượng luồng mà GPU có nhiều hơn gấp 5 lần rưỡi so với số lượng cần thiết cho tính toán thực tế, trong khi các loại CPU khác có thể chỉ có đủ luồng để thực hiện các hoạt động trong phạm vi 1,2 inch. Đây là điểm quan trọng nhất trong GPU. thiết kế. Nếu bạn chỉ có thể nhớ một điều từ hướng dẫn này thì đó là: GPU có nhiều luồng hơn mức thực sự cần vì nó được thiết kế để "đăng ký vượt mức". Nó được thiết kế để đảm bảo rằng một số lượng lớn các luồng đang hoạt động cùng lúc, do đó ngay cả khi một số luồng đang chờ hoạt động bộ nhớ hoàn tất, vẫn có những luồng khác có thể tiếp tục thực thi.

GPU thường được gọi là "máy thông lượng". Các nhà thiết kế GPU dồn mọi nguồn lực của họ vào việc tăng số lượng luồng thay vì giảm độ trễ. Ngược lại, CPU tập trung hơn vào việc giảm độ trễ nên thường được gọi là "máy có độ trễ".CPU mong đợi một luồng duy nhất thực hiện hầu hết công việc. Chuyển đổi luồng trong CPU (chuyển từ luồng này sang luồng khác) là một hoạt động tiêu tốn nhiều tài nguyên liên quan đến chuyển đổi ngữ cảnh, do đó chỉ cần đủ luồng để bù đắp độ trễ bộ nhớ.

Do đó, các nhà thiết kế CPU dồn mọi nguồn lực của mình vào việc giảm độ trễ thay vì tăng số lượng luồng.

Các giải pháp phân luồng của GPU và CPU hoàn toàn trái ngược nhau. Mặc dù chúng được sử dụng để giải quyết cùng một vấn đề về độ trễ nhưng thực chất chúng là điểm khác biệt cơ bản trong chế độ hoạt động và nguyên lý hoạt động của GPU và CPU. Hãy nhớ rằng, các nhà thiết kế GPU chống lại độ trễ bằng cách tăng số lượng luồng chứ không phải bằng cách giảm độ trễ.

Ngoài ra, hãy lưu ý rằng GPU đã được đăng ký vượt mức. Điều này có nghĩa là trong khi một số luồng đang chờ đọc dữ liệu thì các luồng khác đã đọc xong và sẵn sàng thực thi. Đây là mấu chốt của cách GPU hoạt động. Nó có thể dễ dàng chuyển đổi giữa các sợi dọc khác nhau trong một chu kỳ đồng hồ, do đó hầu như không có chi phí chuyển đổi ngữ cảnh. Nó có thể chạy chủ đề liên tục. Điều này có nghĩa là, để bù đắp cho độ trễ, GPU cần duy trì nhiều luồng hoạt động hơn mức hệ thống có thể chạy cùng một lúc. Điều này rất khác với cách hoạt động của CPU, nơi nó không bao giờ muốn có quá nhiều luồng.

Ngoài sự khác biệt về luồng, bộ nhớ cũng là một yếu tố cực kỳ quan trọng trong hoạt động của GPU, bởi mọi công việc lập trình đều xoay quanh bộ nhớ.

Bộ nhớ GPU cần đủ lớn

GPU phân bổ một số lượng lớn thanh ghi cho mỗi luồng để lưu trữ dữ liệu thời gian thực, do đó đạt được độ trễ rất thấp. Điều này là do mỗi luồng trong GPU cần xử lý nhiều dữ liệu hơn CPU nên nó cần có khả năng truy cập dữ liệu này một cách nhanh chóng. Vì vậy, GPU cần một bộ nhớ nhanh gần với lõi tính toán của nó và bộ nhớ này cần đủ lớn để có thể lưu trữ tất cả dữ liệu cần thiết để thực hiện các phép tính hữu ích.

Không chỉ vậy, khi bạn thực hiện một thao tác tải (chẳng hạn như tải giá trị của con trỏ vào biến x), phần cứng cần một nơi để lưu trữ tạm thời kết quả tải. Vì vậy, khi tôi nói tải dữ liệu từ bộ nhớ, thực ra tôi muốn nói đến việc đưa kết quả của lần tải này vào một thanh ghi để có thể thực hiện các phép tính trên đó. Số lượng thanh ghi mà GPU có sẽ xác định trực tiếp số lượng hoạt động bộ nhớ mà nó có thể xử lý đồng thời.

1716719799831.png
Bộ nhớ chính của GPU là bộ nhớ HBM băng thông cao. Nếu coi băng thông của bộ nhớ chính GPU là một đơn vị thì dù nhanh đến mấy cũng chỉ được tính là một. Băng thông bộ đệm L2 gấp 5 lần và bộ đệm L1, bộ nhớ dùng chung mà tôi sắp đề cập, nhanh hơn 13 lần. Vì vậy, khi băng thông tăng lên, việc đáp ứng nhu cầu cường độ tính toán sẽ trở nên dễ dàng hơn, đây chắc chắn là một điều tốt. Nếu có thể, mọi người đều mong có thể tận dụng tối đa bộ đệm để đáp ứng cường độ tính toán.

Chúng ta hãy xem cường độ tính toán cần thiết để mỗi lớp bộ nhớ hoạt động. Đối với HBM, cường độ tính toán mà chúng tôi đã xem xét trước đó là 100. Bộ đệm L2 có cường độ tính toán cao hơn nhiều, chỉ cần 39 thao tác tải và bộ đệm L1 chỉ yêu cầu 8, đây là một con số rất có thể đạt được. Đây là lý do tại sao bộ nhớ đệm L1, bộ nhớ dùng chung và GPU rất hữu ích vì tôi thực sự có thể lấy dữ liệu đủ gần các lõi điện toán để thực hiện 8 thao tác một cách có ý nghĩa và tận dụng tối đa FLOP. Vì vậy, nếu có thể, cải tiến nhờ khả năng đọc tất cả dữ liệu từ bộ đệm là có giá trị nhất.

Tuy nhiên, cần lưu ý rằng băng thông của PCIe rất hạn chế và độ trễ lớn. NVLink gần với bộ nhớ chính hơn PCIe về hiệu năng. Đây là lý do tại sao NVLink tốt hơn nhiều so với bus PCIe khi trở thành phương thức kết nối giữa các chip và giữa các GPU.

Giải thích đơn giản về nguyên lý hoạt động của GPU

Được rồi, sau khi đọc xong nội dung phức tạp ở trên, chúng ta hãy cùng tìm hiểu cơ chế hoạt động của GPU thông qua một số ví dụ sinh động. Đầu tiên hãy nói về thông lượng và độ trễ. Hãy bắt đầu bằng một phép loại suy. Giả sử người này sống ở San Francisco nhưng làm việc ở Santa Clara.

Lúc này, người này có hai lựa chọn để đi làm. Bạn có thể lái xe, chỉ mất 45 phút, hoặc bạn có thể đi tàu, mất 73 phút.

1716720961849.png

Tại thời điểm này, ô tô được thiết kế để giảm độ trễ, nhưng tàu hỏa lại là cỗ máy thông lượng. Hãy tưởng tượng rằng lợi ích của việc lái xe là nó cố gắng hoàn thành hành trình càng nhanh càng tốt nhưng nó không thực sự giúp ích được gì cho người khác. Nó nhanh nhưng không hiệu quả lắm, chỉ chở được vài người và chỉ có thể đi từ nơi này đến nơi khác. Mặt khác, tàu có thể chở rất nhiều người và dừng ở nhiều nơi nên mọi người trên đường đi đều có thể sử dụng tàu để đi làm. Nhiều chuyến tàu có thể được thiết lập để vận chuyển hành khách.

Tại thời điểm này, các ca tàu khác nhau tương đương với hệ thống trễ của GPU. Nếu đăng ký quá mức , hiệu suất sẽ giảm đi rất nhiều. Nhưng nếu có quá nhiều ô tô trên đường, giao thông bị tê liệt và không ai trên ô tô có thể đến đích một cách suôn sẻ. Nhưng một lần nữa, nếu tàu đã đầy, bạn chỉ cần đợi chuyến tiếp theo. Và, không giống như ô tô, sự chậm trễ của tàu thường không kéo dài vì luôn có chuyến tàu tiếp theo.Vì vậy, GPU thực sự có thể được coi là một cỗ máy thông lượng, được thiết kế để xử lý nhiều tác vụ hơn mức có thể chạy cùng một lúc. Nó giống như một hệ thống xe lửa, nếu tàu không chở đầy người thì nó không phát huy hết công suất. Điều này cũng đúng với GPU, hệ thống thông lượng thường muốn có hàng đợi sâu. Công ty tàu hỏa thực sự muốn bạn đợi ở sân ga vì nếu sân ga trống và các toa không đầy khi tàu đến thì họ đang lãng phí tài nguyên. Điều tương tự cũng xảy ra với GPU, cần phải luôn bận rộn để tận dụng tối đa hiệu suất.

CPU giống một cỗ máy có độ trễ hơn. Việc chuyển đổi luồng tiêu tốn tài nguyên, vì vậy CPU muốn mỗi luồng hoàn thành nhiệm vụ của mình càng nhanh càng tốt. Nhưng nếu có quá nhiều nhiệm vụ, hệ thống sẽ bị sa lầy. Vì vậy, mục tiêu của CPU là hoàn thành từng nhiệm vụ càng nhanh càng tốt và sau đó nhường chỗ cho nhiệm vụ tiếp theo. Giống như chúng ta muốn các phương tiện di chuyển thuận lợi trên đường thay vì ùn tắc vì số lượng phương tiện trên đường có hạn. Nói tóm lại, chúng ta tận dụng những luồng này để giải quyết vấn đề về độ trễ, đây là một chiến lược rất hiệu quả.Bây giờ chúng ta đã hiểu vấn đề về độ trễ, hãy xem xét thách thức về băng thông. Vì toàn bộ hệ thống được thiết kế dựa trên thông lượng nên GPU thường đăng ký vượt mức tài nguyên. Điều này có nghĩa là GPU luôn có nhiệm vụ thực thi và bộ nhớ liên tục được truy cập.

Trong quá trình này, chúng ta phải xem xét tính không đồng bộ. Điều quan trọng cần lưu ý là CPU và GPU là các bộ xử lý độc lập, nghĩa là chúng có thể xử lý các tác vụ khác nhau cùng một lúc và đúng như vậy. Nếu CPU ngừng chờ GPU hoặc GPU ngừng chờ CPU thì hiệu quả của toàn bộ hệ thống sẽ giảm. Nó giống như việc phải đợi chuyến tàu tiếp theo ở mỗi ga trước khi tiếp tục, điều này rõ ràng là không tốt bằng việc chỉ có một bộ xử lý hiệu quả.

Tầm quan trọng của tính không đồng bộ là nó giữ cho tất cả các bộ xử lý hoạt động và không ai dừng lại và chờ đợi. CPU có thể gửi hướng dẫn công việc đến GPU và sau đó tiếp tục thực hiện các tác vụ khác, trong khi GPU xử lý các tác vụ này một cách độc lập. Chúng ta chỉ cần chờ kết quả cuối cùng.

1716721028979.png

Để giải thích khái niệm này một cách sinh động hơn, chúng ta có thể hình dung giao thông đường bộ. Nếu bạn muốn di chuyển nhiều đồ cùng một lúc thì bạn cần có nhiều làn đường hơn, chẳng hạn như đường bên phải. Giao thông như vậy không đồng bộ, mỗi xe có thể độc lập di chuyển về phía trước mà không bị xe phía trước chặn lại vì có đủ làn đường. Ngược lại, nếu giao thông đồng bộ thì chỉ có một làn đường và tất cả các phương tiện đều phải chờ xe chậm nhất, hiệu quả sẽ giảm đi rất nhiều. Do đó, tính không đồng bộ rất quan trọng đối với thông lượng cao mà chúng tôi cố gắng đạt được.

1716721058655.png

Tuy nhiên, trong thế giới thực, rất ít công việc hoàn toàn khép kín. DAXPY là một ví dụ điển hình. Chúng được gọi là thuật toán theo phần tử và chỉ những thuật toán đơn giản nhất mới hoạt động theo cách này. Hầu hết các thuật toán đều yêu cầu ít nhất một hoặc nhiều phần tử, chẳng hạn như phép toán tích chập, xem xét mọi pixel trong hình ảnh và các pixel lân cận của nó. Ngoài ra còn có các thuật toán, chẳng hạn như biến đổi Fourier, yêu cầu mỗi phần tử tương tác với mọi phần tử khác. Chúng được gọi là thuật toán tổng hợp và chúng hoạt động theo cách rất khác so với thuật toán theo từng phần tử.

Làm cách nào để đạt được thông lượng trong quá trình làm việc của GPU?

Bây giờ, chúng ta hãy xem cách xử lý song song hoạt động trên GPU và cách GPU đạt được thông lượng cần thiết.

Giả sử rằng AI được đào tạo để nhận dạng mèo trên Internet. Bây giờ chúng ta có hình ảnh một con mèo. Tôi sẽ phủ hình ảnh này bằng một lưới chia hình ảnh thành một số khối làm việc. Sau đó tôi làm việc trên từng phần công việc một cách độc lập. Các khối công việc này độc lập với nhau, chúng hoạt động trên các phần khác nhau của bức tranh và số lượng khối công việc rất lớn. Do đó, GPU sẽ bị đăng ký quá mức bởi các khối công việc này. Nhưng hãy nhớ rằng đăng ký vượt mức là chiến lược chúng tôi sử dụng để theo đuổi việc thực thi hiệu quả và sử dụng bộ nhớ tối đa.

1716721121988.png

Trong mỗi khối công việc, có nhiều luồng làm việc cùng nhau. Các luồng này có thể chia sẻ dữ liệu và hoàn thành các tác vụ chung. Tất cả các luồng chạy song song cùng một lúc, do đó GPU có thể đạt được khả năng xử lý song song hiệu quả. Bây giờ, hệ thống phân cấp đã được xây dựng. Ở cấp cao nhất, có tổng khối lượng công việc được chia thành các phần công việc thông qua lưới, cung cấp lượng đăng ký vượt mức cần thiết cho GPU. Sau đó, trong mỗi khối công việc, có một số luồng cục bộ hoạt động cùng nhau. Bằng cách này, khả năng xử lý song song của GPU có thể được tận dụng tối đa để đạt được thông lượng hiệu quả.

1716721150372.png

Điều này tập hợp những điều tốt nhất của cả hai hoạt động. Nó giữ cho máy luôn bận rộn và cung cấp thông lượng cần thiết đồng thời cho phép tương tác cần thiết giữa các luồng. Đây là bản chất của lập trình GPU: chia vấn đề thành nhiều phần, trong đó các luồng hợp tác làm việc cùng nhau để xử lý tác vụ và mỗi phần vẫn tương đối độc lập.

Được rồi, tôi đã trình bày chi tiết về cách hoạt động của GPU. Độ trễ bị che giấu bởi việc đăng ký quá mức, nhưng độ trễ thực sự là chìa khóa thành công của GPU. Tất cả những điều này - số lượng lớn các luồng, đăng ký vượt mức, mô hình lập trình lưới và khối cũng như các luồng chạy trong khối - tất cả đều tồn tại để chống lại độ trễ. Giờ đây GPU NVIDIA đã làm được điều đó và đạt được thành công, nhưng hiện tại chúng tôi đang bị giới hạn bởi băng thông, đây là trọng tâm trong quá trình nghiên cứu và phát triển tiếp theo của NVIDIA.
 


Đăng nhập một lần thảo luận tẹt ga
Top