Bagaimana cara CUDA memblokir / melengkungkan / utas memetakan ke inti CUDA?

142

Saya telah menggunakan CUDA selama beberapa minggu, tetapi saya memiliki keraguan tentang alokasi blok / warps / utas. Saya mempelajari arsitektur dari sudut pandang didaktik (proyek universitas), jadi mencapai kinerja puncak bukan urusan saya.

Pertama-tama, saya ingin memahami jika saya mengemukakan fakta-fakta ini:

  1. Programmer menulis kernel, dan mengatur pelaksanaannya dalam kotak blok thread.

  2. Setiap blok ditugaskan ke Streaming Multiprocessor (SM). Setelah ditugaskan itu tidak dapat bermigrasi ke SM lain.

  3. Setiap SM membagi bloknya sendiri menjadi Warps (saat ini dengan ukuran maksimum 32 utas). Semua utas dalam warp dieksekusi bersamaan pada sumber daya SM.

  4. Eksekusi aktual sebuah thread dilakukan oleh CUDA Cores yang terkandung dalam SM. Tidak ada pemetaan khusus antara utas dan inti.

  5. Jika sebuah warp berisi 20 utas, tetapi saat ini hanya ada 16 core yang tersedia, warp tidak akan berjalan.

  6. Di sisi lain, jika sebuah blok berisi 48 utas, ia akan dibagi menjadi 2 lungsin dan akan dieksekusi secara paralel asalkan tersedia cukup memori.

  7. Jika sebuah thread dimulai pada sebuah core, maka itu macet untuk akses memori atau untuk operasi floating point yang panjang, pelaksanaannya dapat dilanjutkan pada core yang berbeda.

Apakah mereka benar

Sekarang, saya memiliki GeForce 560 Ti sehingga sesuai dengan spesifikasi dilengkapi dengan 8 SM, masing-masing berisi 48 core CUDA (total 384 core).

Tujuan saya adalah memastikan bahwa setiap inti arsitektur mengeksekusi instruksi SAMA. Dengan asumsi bahwa kode saya tidak akan memerlukan lebih banyak register daripada yang tersedia di setiap SM, saya membayangkan pendekatan yang berbeda:

  1. Saya membuat 8 blok dari 48 utas masing-masing, sehingga setiap SM memiliki 1 blok untuk dieksekusi. Dalam hal ini akankah 48 thread dieksekusi secara paralel di SM (mengeksploitasi semua 48 core yang tersedia untuk mereka)?

  2. Apakah ada perbedaan jika saya meluncurkan 64 blok dari 6 utas? (Dengan asumsi bahwa mereka akan dipetakan secara merata di antara SM)

  3. Jika saya "menenggelamkan" GPU dalam pekerjaan terjadwal (membuat 1024 blok masing-masing 1024 utas, misalnya) apakah masuk akal untuk menganggap bahwa semua inti akan digunakan pada titik tertentu, dan akan melakukan perhitungan yang sama (dengan asumsi bahwa utas tidak pernah warung)?

  4. Apakah ada cara untuk memeriksa situasi ini menggunakan profiler?

  5. Apakah ada referensi untuk barang ini? Saya membaca panduan Pemrograman CUDA dan bab-bab yang didedikasikan untuk arsitektur perangkat keras dalam "Pemrograman Proses Masif Paralel" dan "Desain dan pengembangan aplikasi CUDA"; tetapi saya tidak bisa mendapatkan jawaban yang tepat.

Daedalus
sumber
Saya ingin menambahkan apa yang disebut "inti CUDA". "Inti CUDA" atau "Unit eksekusi" adalah integer ALU dan FPU pipelined sepenuhnya yang mengeksekusi satu instruksi instruksi aritmatika per siklus clock dalam satu thread cuda.
bruziuz

Jawaban:

123

Dua referensi terbaik adalah

  1. NVIDIA Fermi Compute Whitepaper Architecture
  2. GF104 Ulasan

Saya akan mencoba menjawab setiap pertanyaan Anda.

Programmer membagi pekerjaan menjadi utas, utas menjadi blok-blok thread, dan blok-blok thread menjadi grid. Distributor pekerjaan komputasi mengalokasikan blok thread ke Streaming Multiprocessors (SMs). Setelah blok thread didistribusikan ke SM, sumber daya untuk blok thread dialokasikan (lungsin dan memori bersama) dan utas dibagi ke dalam kelompok 32 utas yang disebut warps. Setelah sebuah warp dialokasikan, itu disebut warp aktif. Kedua penjadwal warp memilih dua warps aktif per siklus dan mengirimkan warps ke unit eksekusi. Untuk detail lebih lanjut tentang unit eksekusi dan pengiriman instruksi lihat 1 hal.7-10 dan 2 .

4' . Ada pemetaan antara laneid (indeks thread dalam warp) dan inti.

5 ' . Jika sebuah warp mengandung kurang dari 32 utas, dalam kebanyakan kasus akan dieksekusi sama seperti jika memiliki 32 utas. Warps dapat memiliki kurang dari 32 utas aktif karena beberapa alasan: jumlah utas per blok tidak dapat dibagi oleh 32, program menjalankan blok divergen sehingga utas yang tidak mengambil jalur saat ini ditandai tidak aktif, atau utas di warp keluar.

6 ' . Blok thread akan dibagi menjadi WarpsPerBlock = (ThreadsPerBlock + WarpSize - 1) / WarpSize Tidak ada persyaratan bagi penjadwal warp untuk memilih dua warps dari blok thread yang sama.

7 ' . Unit eksekusi tidak akan menghentikan operasi memori. Jika sumber daya tidak tersedia ketika instruksi siap dikirim, instruksi akan dikirim lagi di masa mendatang ketika sumber daya tersedia. Lengkungan dapat terhenti pada hambatan, pada operasi memori, operasi tekstur, dependensi data, ... Lengkungan yang terhenti tidak memenuhi syarat untuk dipilih oleh penjadwal warp. Pada Fermi, berguna untuk memiliki setidaknya 2 warps yang memenuhi syarat per siklus sehingga penjadwal warp dapat mengeluarkan instruksi.

Lihat referensi 2 untuk perbedaan antara GTX480 dan GTX560.

Jika Anda membaca materi referensi (beberapa menit) saya pikir Anda akan menemukan bahwa tujuan Anda tidak masuk akal. Saya akan mencoba menanggapi poin Anda.

1 ' . Jika Anda meluncurkan kernel <<< 8, 48 >>> Anda akan mendapatkan 8 blok masing-masing dengan 2 lilitan 32 dan 16 utas. Tidak ada jaminan bahwa 8 blok ini akan ditugaskan untuk SM yang berbeda. Jika 2 blok dialokasikan ke SM maka ada kemungkinan bahwa setiap penjadwal warp dapat memilih warp dan mengeksekusi warp. Anda hanya akan menggunakan 32 dari 48 core.

2 ' . Ada perbedaan besar antara 8 blok 48 thread dan 64 blok 6 thread. Mari kita asumsikan bahwa kernel Anda tidak memiliki divergensi dan setiap utas mengeksekusi 10 instruksi.

  • 8 blok dengan 48 utas = 16 warps * 10 instruksi = 160 instruksi
  • 64 blok dengan 6 utas = 64 warps * 10 instruksi = 640 instruksi

Untuk mendapatkan efisiensi yang optimal, pembagian pekerjaan harus dalam kelipatan 32 utas. Perangkat keras tidak akan menyatukan utas dari warps yang berbeda.

3 ' . GTX560 dapat memiliki 8 blok SM * 8 = 64 blok sekaligus atau 8 SM * 48 warps = 512 warps jika kernel tidak memaksimalkan register atau memori bersama. Pada waktu tertentu sebagian pekerjaan akan aktif di SM. Setiap SM memiliki beberapa unit eksekusi (lebih dari inti CUDA). Sumber daya mana yang digunakan pada waktu tertentu tergantung pada penjadwalan warp dan campuran instruksi aplikasi. Jika Anda tidak melakukan operasi TEX maka unit TEX akan menganggur. Jika Anda tidak melakukan operasi floating point khusus, unit SUFU akan menganggur.

4' . Paralel Nsight dan pertunjukan Visual Profiler

Sebuah. IPC dieksekusi

b. mengeluarkan IPC

c. warps aktif per siklus aktif

d. warps yang memenuhi syarat per siklus aktif (hanya Nsight)

e. alasan warp warung (khusus Nsight)

f. utas aktif per instruksi dieksekusi

Profiler tidak menunjukkan persentase pemanfaatan unit eksekusi mana pun. Untuk GTX560, perkiraan kasar akan dikeluarkan IssIPIP / MaxIPC. Untuk MaxIPC anggap GF100 (GTX480) adalah 2 GF10x (GTX560) adalah 4 tetapi target 3 adalah target yang lebih baik.

Greg Smith
sumber
1
Terima kasih atas jawaban Anda. Saya membaca referensi, tetapi ada beberapa hal yang saya tidak mengerti dalam jawaban Anda. Dalam pertanyaan-pertanyaan berikut, saya mengasumsikan bahwa kami menggunakan arsitektur Fermi dengan 48 core (16 core * 3 "grup inti"): 1. Anda menyebutkan pemetaan antara core dan laneid. Pemetaan seperti apa itu? 2. Dari referensi yang saya dapatkan bahwa setiap "kelompok inti" mengeksekusi paling banyak setengah-warp (16 thread) per siklus clock. Jadi secara teori jika kita memiliki 48 utas di blok yang sama, mereka akan disusun menjadi 3 setengah lungsin dan dieksekusi secara paralel pada 48 core. Apakah saya benar?
Daedalus
1
Core CUDA adalah jumlah unit FP presisi tunggal. Memikirkan eksekusi dalam hal inti CUDA tidak benar. Setiap warp memiliki 32 utas. Utas ini akan dikeluarkan untuk sekelompok unit eksekusi (mis. 16 inti kartu). Untuk mengeluarkan ke semua 48 core dalam satu jam tunggal, salah satu dari dua penjadwal warp perlu memilih warp yang memenuhi req dari pasangan superscalar dan kedua instruksi harus dari tipe yang dieksekusi oleh core CUDA. Selain itu penjadwal warp lain harus memilih warp yang instruksi selanjutnya akan dieksekusi oleh core CUDA.
Greg Smith
1
Tidak ada persyaratan bahwa lungsin berada di blok yang sama atau bahwa lungsin di blok memiliki counter program yang sama.
Greg Smith
2
Dalam contoh Anda, setiap penjadwal memilih lungsin dan mengeluarkan 1 instruksi. Dalam hal ini hanya 2 kelompok unit eksekusi yang akan digunakan. Untuk menggunakan lebih banyak unit eksekusi, 1 penjadwal harus memiliki dua masalah. Seperti yang ditunjukkan dalam referensi ada beberapa jenis unit eksekusi (bukan hanya apa yang diciptakan cuda core) dan ada aturan memasangkan instruksi (tidak didokumentasikan dengan baik) yang harus dipenuhi untuk penjadwal untuk masalah ganda.
Greg Smith
1
@ GregSmith saya sedang mencari di seluruh web untuk mencari tahu dari mana 8 blok aktif per SM ini berasal dari arsitektur Fermi. Bahkan tidak disebutkan dalam kertas putih fermi. Apakah Anda punya referensi lagi tentang itu?
Greg K.
8

"E. Jika sebuah warp berisi 20 utas, tetapi saat ini hanya ada 16 inti yang tersedia, warp tidak akan berjalan."

salah. Anda adalah core yang membingungkan dalam pengertian biasanya (juga digunakan dalam CPU) - jumlah "multiprosesor" dalam GPU, dengan core dalam bahasa pemasaran nVIDIA ("kartu kami memiliki ribuan core CUDA").

Sebuah warp itu sendiri hanya dapat dijadwalkan pada satu inti (= multiprosesor), dan dapat berjalan hingga 32 utas pada saat yang sama; tidak dapat menggunakan lebih dari satu inti.

Angka "48 warps" adalah jumlah maksimum warp aktif (warps yang dapat dipilih untuk dijadwalkan untuk bekerja pada siklus berikutnya, pada siklus apa pun yang diberikan) per multiprosesor, pada GPU nVIDIA dengan Kemampuan Komputasi 2.x; dan jumlah ini sesuai dengan 1536 = 48 x 32 utas.

Jawaban berdasarkan webinar ini

Andrej
sumber
@ Greg Regs: Diedit jawaban untuk mengatasi ini Tidak apa-apa kamu bersabar dengan itu, tapi - sudah lima tahun ...
einpoklum
single core (= multiprosesor)? Saya pikir pertanyaan mengasumsikan terminologi single core = prosesor dan bukan multiprosesor. Dengan terminologi Anda, jawaban Anda benar.
Adarsh