Mengapa keamanan utas merupakan masalah besar bagi Grafik API?

21

Baik Vulkan dan DirectX12 diklaim dapat digunakan dengan cara yang aman. Orang-orang tampaknya bersemangat tentang hal itu.

Mengapa ini dianggap sebagai fitur yang sangat besar? Pemrosesan "nyata" akan dilemparkan ke atas jembatan memori pada unit pemrosesan terpisah.

Juga jika itu sangat besar, mengapa tidak sampai sekarang bahwa API API aman thread keluar?

ratchet freak
sumber
Artikel ini jauh lebih "gamer fokus" tetapi mungkin memberi Anda beberapa wawasan ... pcgamer.com/what-directx-12-means-for-gamers-and-developers
glampert

Jawaban:

13

Keuntungan utama adalah bahwa akan lebih mudah untuk membagi tugas-tugas CPU menjadi beberapa utas, tanpa harus menyelesaikan semua masalah sulit dengan mengakses API grafik. Biasanya Anda harus membuat konteks saat ini (yang mungkin memiliki implikasi kinerja yang buruk) atau memberikan antrian dan memanggil api grafis dalam satu utas. Saya tidak berpikir bahwa kinerja apa pun diperoleh dengan cara ini, karena GPU memang memprosesnya secara berurutan, tetapi itu membuat pekerjaan pengembang jauh lebih mudah.

Alasan bahwa itu tidak dilakukan sampai sekarang mungkin adalah karena directx dan opengl dibuat pada saat multithreading tidak benar-benar terlihat. Juga dewan Khronos sangat konservatif dalam mengubah API. Pandangan mereka tentang Vulkan juga akan berdampingan dengan OpenGL, karena keduanya memiliki tujuan yang berbeda. Barangkali baru-baru ini paralisme menjadi begitu penting, karena konsumen mendapatkan akses ke semakin banyak prosesor.

EDIT: Saya tidak bermaksud bahwa tidak ada kinerja yang diperoleh dari melakukan pekerjaan di banyak CPU, itu tidak berguna untuk membagi panggilan Anda menjadi beberapa utas untuk membuat tekstur / shader lebih cepat. Sebaliknya kinerja diperoleh karena memiliki lebih banyak prosesor yang sibuk dan membuat GPU sibuk dengan hal-hal untuk dilakukan.

Maurice Laveaux
sumber
1
Sebagai catatan tambahan, OpenGL umumnya hanya bekerja pada satu utas sehingga aplikasi intensif grafis dapat memaksimalkan satu inti. Sesuatu seperti Vulkan memungkinkan banyak utas untuk mengirim perintah ke antrian yang berarti banyak panggilan grafis dapat dibuat dari banyak utas.
Soapy
9

Ada banyak pekerjaan yang diperlukan pada CPU untuk mengatur bingkai untuk GPU, dan sebagian besar pekerjaan itu ada di dalam driver grafis. Sebelum DX12 / Vulkan, pekerjaan driver grafis itu pada dasarnya dipaksa untuk single-threaded oleh desain API.

Harapannya adalah bahwa DX12 / Vulkan mengangkat pembatasan itu, yang memungkinkan pekerjaan pengemudi dilakukan secara paralel pada beberapa utas CPU dalam sebuah bingkai. Ini akan memungkinkan penggunaan multicore CPU yang lebih efisien, memungkinkan mesin game untuk mendorong adegan yang lebih kompleks tanpa menjadi terikat CPU. Itulah harapan — apakah itu akan diwujudkan dalam praktik adalah sesuatu yang harus kita tunggu untuk melihat selama beberapa tahun ke depan.

Untuk menguraikan sedikit: output dari mesin renderer permainan adalah aliran panggilan API DX / GL yang menggambarkan urutan operasi untuk membuat bingkai. Namun, ada jarak yang sangat jauh antara aliran panggilan API dan buffer perintah biner aktual yang dikonsumsi perangkat keras GPU. Pengemudi harus "mengkompilasi" panggilan API ke dalam bahasa mesin GPU, jadi untuk berbicara. Itu bukan proses yang sepele — ini melibatkan banyak penerjemahan konsep API ke dalam realitas perangkat keras tingkat rendah, validasi untuk memastikan GPU tidak pernah disetel ke keadaan tidak valid, mengacaukan alokasi memori dan data, melacak perubahan status untuk mengeluarkan perbaiki perintah tingkat rendah, dan seterusnya. Driver grafis bertanggung jawab untuk semua hal ini.

Di DX11 / GL4 dan API sebelumnya, pekerjaan ini biasanya dilakukan oleh utas driver tunggal. Bahkan jika Anda memanggil API dari banyak utas (yang dapat Anda lakukan menggunakan daftar perintah yang ditangguhkan DX11, misalnya), itu hanya menambahkan beberapa pekerjaan ke antrian agar utas pengandar dapat dikunyah nanti. Satu alasan besar untuk ini adalah pelacakan negara yang saya sebutkan sebelumnya. Banyak detail konfigurasi GPU tingkat perangkat keras yang memerlukan pengetahuan tentang keadaan jalur pipa grafis saat ini, jadi tidak ada cara yang baik untuk memecah daftar perintah menjadi potongan-potongan yang dapat diproses secara paralel — setiap potongan harus tahu persis apa yang harus dimulai. dengan, meskipun potongan sebelumnya belum diproses.

Itu salah satu hal besar yang berubah di DX12 / Vulkan. Untuk satu hal, mereka menggabungkan hampir semua keadaan pipa grafis ke dalam satu objek, dan untuk yang lain (setidaknya dalam DX12) ketika Anda mulai membuat daftar perintah Anda harus memberikan keadaan pipa awal; negara tidak diwarisi dari satu daftar perintah ke yang berikutnya. Pada prinsipnya, ini memungkinkan pengemudi untuk tidak perlu tahu apa-apa tentang daftar perintah sebelumnya sebelum dapat mulai mengkompilasi — dan yang pada gilirannya memungkinkan aplikasi untuk memecah render menjadi potongan paralel, menghasilkan daftar perintah yang sepenuhnya dikompilasi, yang kemudian dapat digabungkan bersama-sama dan dikirim ke GPU dengan sedikit keributan.

Tentu saja, ada banyak perubahan lain di API baru, tetapi sejauh multithreading berjalan, itulah bagian terpenting.

Nathan Reed
sumber
5

GPU modern umumnya memiliki bagian frontend tunggal yang memproses aliran perintah yang sepenuhnya linier dari CPU. Apakah ini adalah desain perangkat keras alami atau jika itu hanya berevolusi dari hari-hari ketika ada satu CPU menghasilkan perintah inti untuk GPU masih bisa diperdebatkan, tapi itu kenyataan untuk saat ini. Jadi, jika Anda menghasilkan aliran linear tunggal perintah stateful, tentu saja masuk akal untuk menghasilkan aliran itu secara linier pada satu utas pada CPU! Kanan?

Nah, GPU modern juga umumnya memiliki backend terpadu yang sangat fleksibel yang dapat bekerja pada banyak hal yang berbeda sekaligus. Secara umum, GPU bekerja pada simpul dan piksel dengan rincian yang cukup baik. Tidak ada banyak perbedaan antara pemrosesan GPU 1024 simpul dalam satu imbang dan 512 + 512 simpul dalam dua imbang yang berbeda.

Itu menunjukkan cara yang cukup alami untuk melakukan lebih sedikit pekerjaan: alih-alih melemparkan sejumlah besar simpul pada GPU dalam satu panggilan undian, pisahkan model Anda menjadi beberapa bagian, lakukan pemusnahan kasar yang murah pada bagian-bagian itu, dan serahkan setiap potongan secara terpisah jika melewati tes pemusnahan. Jika Anda melakukannya di granularity yang tepat, Anda harus mendapatkan speedup yang bagus!

Sayangnya, dalam realitas API grafis saat ini, panggilan draw sangat mahal pada CPU. Penjelasan yang disederhanakan tentang mengapa: perubahan status pada GPU mungkin tidak secara langsung sesuai dengan panggilan API grafis, begitu banyak panggilan API grafis hanya mengatur beberapa keadaan di dalam driver, dan panggilan draw yang akan tergantung pada keadaan baru ini berjalan dan melihat semua negara yang ditandai telah berubah sejak undian terakhir, menulisnya ke dalam aliran perintah untuk GPU, kemudian benar-benar memulai undian. Ini semua pekerjaan yang dilakukan dalam upaya untuk mendapatkan stream perintah ramping dan rata-rata untuk unit frontend GPU.

Apa intinya adalah bahwa Anda memiliki anggaran untuk panggilan draw yang sepenuhnya dibebankan oleh overhead pengemudi . (Saya pikir saya mendengar bahwa hari ini Anda dapat pergi dengan sekitar 5.000 per frame untuk judul FPS 60). Anda dapat meningkatkannya dengan persentase besar dengan membangun aliran perintah ini dalam potongan paralel.

Ada alasan lain juga (misalnya, timewarp asinkron untuk peningkatan latensi VR), tetapi ini adalah alasan besar untuk gim-gim yang terikat grafis dan perangkat lunak penarik panggilan lainnya (seperti paket pemodelan 3D).

John Calsbeek
sumber