Membuat bot untuk berpartisipasi dalam cangkir mini AI. Pengalaman GPU


Kelanjutan Pasal 1 dan Pasal 2 .


Di bawah potongan ini, saya akan berbicara tentang pengalaman penulis dalam menggunakan GPU untuk perhitungan, termasuk sebagai bagian dari pembuatan bot untuk berpartisipasi dalam piala mini AI. Melainkan, ini adalah esai tentang masalah GPU.


- Namamu ajaib ...
-Apakah kamu tahu, Joel? .. Keajaiban itu pergi ...


Di masa kanak-kanak, kita berbicara tentang usia ketika kimia belum berjalan di sekolah atau baru mulai terjadi, penulis terpesona oleh reaksi pembakaran, kebetulan orang tuanya tidak mengganggu dia dan gurun Moskow dekat rumah kadang-kadang diterangi oleh berbagai aktivitas anak-anak, roket buatan sendiri berwarna hitam bubuk mesiu, pada karamel gula-nitrat, dll. Dua keadaan membatasi fantasi anak-anak: dekomposisi nitrogliserin di laboratorium rumah dengan langit-langit berdesis dari asam dan dorongan ke ruang polisi dalam upaya untuk mendapatkan bahan kimia di salah satu perusahaan pertahanan yang tersebar di sekitar wilayah metro Aviamotornaya.


Dan kemudian sebuah sekolah fisika dengan komputer yamaha msx muncul, kalkulator MK yang dapat diprogram di rumah, dan tidak ada waktu untuk kimia. Kepentingan anak telah bergeser ke komputer. Dan apa yang kurang dari penulis dari kenalan pertama dengan komputer adalah reaksi terbakar, program-programnya membara, tidak ada sensasi kekuatan alami ini. Anda bisa melihat proses mengoptimalkan perhitungan dalam permainan, tetapi pada saat itu penulis tidak tahu bagaimana cara mengganti perhitungan dosa () dengan tabel nilai fungsi ini, tidak ada Internet ...


Jadi, penulis bisa mendapatkan perasaan senang dari daya komputasi, pembakaran bersih, saya menggunakan GPU dalam perhitungan.


Pada habr ada beberapa artikel bagus tentang perhitungan pada GPU. Ada juga banyak contoh di Internet, jadi diputuskan untuk hanya menulis pada hari Sabtu pagi tentang perasaan pribadi dan dimungkinkan untuk mendorong orang lain menuju paralelisme massa.


Mari kita mulai dengan formulir sederhana. Komputasi GPU mendukung beberapa kerangka kerja, tetapi yang paling terkenal adalah NVIDIA CUDA dan OpenCL. Kami akan mengambil CUDA dan segera kami harus mempersempit set bahasa pemrograman kami ke C ++. Ada perpustakaan untuk menghubungkan ke CUDA dalam bahasa pemrograman lain, misalnya, ALEA GPU dalam C #, tetapi ini lebih merupakan topik dari artikel ulasan terpisah.


Karena mereka tidak dapat membuat mobil massal dengan mesin jet pada satu waktu, meskipun beberapa indikatornya lebih tinggi daripada mesin pembakaran internal, perhitungan paralel tidak selalu mungkin untuk diterapkan dalam masalah nyata. Aplikasi utama untuk komputasi paralel: Anda memerlukan tugas yang mengandung beberapa elemen karakter massal, multiplisitas. Dalam kasus kami membuat bot, jaringan saraf (banyak neuron, koneksi saraf) jatuh di bawah massa dan populasi bot (menghitung dinamika pergerakan, tabrakan untuk setiap bot membutuhkan waktu, jika bot dari 300-1000 maka prosesor pusat menyerah dan Anda akan mengamati hanya lambat) membara program Anda, seperti jeda panjang antara frame visualisasi).


Pilihan massa terbaik adalah ketika setiap elemen perhitungan tidak bergantung pada hasil perhitungan pada elemen lain dari daftar, misalnya, tugas sederhana menyortir array sudah ditumbuhi semua jenis trik, karena posisi angka dalam array tergantung pada angka lain dan tidak dapat dimasukkan ke dahi pada siklus paralel . Untuk menyederhanakan kata-kata: tanda pertama dari karakter massa yang sukses adalah bahwa jika Anda tidak perlu mengubah posisi elemen dalam array, Anda dapat dengan bebas melakukan perhitungan di atasnya, mengambil nilai-nilai elemen lain untuk ini, tetapi jangan memindahkannya dari tempatnya. Sesuatu seperti dongeng: jangan mengubah urutan elemen, jika tidak GPU akan berubah menjadi labu.


Dalam bahasa pemrograman modern, ada konstruksi yang dapat dieksekusi secara paralel pada beberapa inti prosesor pusat atau utas logis dan mereka banyak digunakan, tetapi penulis memfokuskan pembaca pada paralelisme massa, ketika jumlah modul yang dieksekusi melebihi ratusan atau ribuan unit.


Elemen pertama dari struktur paralel muncul: siklus paralel . Untuk sebagian besar tugas, itu sudah cukup. Dalam arti luas, inilah intisari
komputasi paralel.


Contoh penulisan loop utama di CUDA (kernel):


int tid = blockIdx.x * blockDim.x + threadIdx.x; int threadN = gridDim.x * blockDim.x; for (int pos = tid; pos < numElements; pos += threadN) { //    pos,     ,       thread     pos.  :    thread    ,  thread   pos=1146     thread c  pos=956.        .           . } 

Banyak yang telah ditulis dalam dokumentasi dan ulasan untuk CUDA , tentang blok GPU, tentang Thread yang diproduksi di blok ini, bagaimana cara memparalelkan tugas pada mereka. Tetapi jika Anda memiliki array data dan itu jelas terdiri dari elemen massa, gunakan bentuk loop di atas, karena secara visual mirip dengan loop biasa dalam bentuk, yang menyenangkan, tetapi sayangnya tidak dalam konten.


Saya pikir pembaca sudah mengerti bahwa kelas tugas dengan cepat menyempit dalam kaitannya dengan pemrograman paralel massa. Jika kita berbicara tentang membuat game, mesin rendering 3d, jaringan saraf, pengeditan video, dan tugas serupa lainnya, maka pembersihan untuk tindakan pembaca independen sangat usang, ada program besar, program kecil, kerangka kerja, pustaka yang dikenal dan tidak dikenal untuk tugas-tugas ini. Artinya, area tersebut tetap hanya dari topik, untuk membuat roket komputasi kecil Anda sendiri, bukan SpaceX dan Roscosmos, tetapi sesuatu yang sederhana, tetapi benar-benar jahat dalam perhitungan.



Berikut adalah gambar roket yang benar-benar menyala yang digambarkan.


Berbicara tentang tugas-tugas yang tidak dapat dipecahkan oleh siklus paralel di tangan Anda. Dan pencipta CUDA dalam pribadi pengembang NVIDIA telah memikirkan hal ini.


Ada perpustakaan Thrust di beberapa tempat yang berguna sampai "tidak ada opsi" dilakukan secara berbeda. Omong-omong, tidak menemukan ulasan lengkap tentang Habré.


Untuk memahami cara kerjanya, pertama-tama Anda perlu mengatakan tiga kalimat tentang prinsip-prinsip CUDA. Jika Anda membutuhkan lebih banyak kata, Anda dapat membaca tautannya.


Prinsip-prinsip CUDA:


Perhitungan dilakukan pada GPU, program yang merupakan kernel, dan Anda harus menuliskannya dalam C. Kernel, pada gilirannya, hanya berkomunikasi dengan memori GPU dan Anda harus memuat data ke dalam memori prosesor video dari program utama dan mengunggahnya kembali ke program. Algoritma canggih pada CUDA membutuhkan fleksibilitas pikiran.


Jadi, perpustakaan Thrust menghapus rutin dan mengambil beberapa tugas "kompleks" untuk CUDA, seperti menjumlahkan array atau mengurutkannya. Anda tidak perlu lagi menulis kernel terpisah, memuat pointer ke memori, dan menyalin data dari pointer ini ke memori GPU. Semua misteri akan terjadi di depan mata Anda di program utama dan dengan kecepatan sedikit lebih rendah daripada CUDA. Perpustakaan Thrust ditulis dalam CUDA, jadi ini adalah bidang beri tunggal dalam hal kinerja.


Yang perlu Anda lakukan di Thrust adalah membuat array (thrust :: vector) di dalam library-nya, yang kompatibel dengan array reguler (std :: vector). Itu, tentu saja, tidak semuanya begitu sederhana, tetapi makna dari apa yang penulis katakan mirip dengan kebenaran. Sebenarnya ada dua array, satu di GPU (perangkat), yang lain di program utama (host).


Contoh akan menunjukkan kesederhanaan dari sintaks (X, Y, Z array):


 // initialize X to 0,1,2,3, .... thrust::sequence(X.begin(), X.end()); // compute Y = -X thrust::transform(X.begin(), X.end(), Y.begin(), thrust::negate<int>()); // fill Z with twos thrust::fill(Z.begin(), Z.end(), 2); // compute Y = X mod 2 thrust::transform(X.begin(), X.end(), Z.begin(), Y.begin(), thrust::modulus<int>()); // replace all the ones in Y with tens thrust::replace(Y.begin(), Y.end(), 1, 10); 

Anda dapat melihat betapa tidak berbahaya tampilannya dengan latar belakang membuat kernel CUDA, dan serangkaian fungsi di Thrust besar . Mulai dari bekerja dengan variabel acak, yang dalam CUDA dilakukan oleh pustaka cuRAND yang terpisah (lebih disukai dijalankan oleh kernel terpisah), untuk menyortir, menjumlahkan, dan menulis fungsi Anda sesuai dengan fungsionalitas yang dekat dengan fungsi kernel.


Penulis memiliki sedikit pengalaman menggunakan CUDA dan C ++, dua bulan. Tentang tahun ini tentang C #. Ini, tentu saja, sedikit bertentangan dengan permulaan artikel tentang kenalan awalnya dengan komputer, fisika sekolah, dan matematika terapan sebagai pendidikan. Saya akan bilang begitu. Tetapi mengapa saya menulis artikel ini, bukan karena saya menguasai semuanya seperti itu, tetapi bahwa C ++ ternyata menjadi bahasa yang nyaman (saya dulu agak takut akan hal itu, dengan latar belakang artikel dalam jenis Haber “fungsi lambda → kelebihan beban operator internal, seperti mendefinisikan ulang segalanya "), jelas bahwa tahun-tahun perkembangannya telah menyebabkan lingkungan pengembangan yang cukup ramah (IDE). Bahasa itu sendiri dalam versi terbarunya, sepertinya mengumpulkan sampah dari memori, saya tidak tahu bagaimana itu sebelumnya. Setidaknya, program yang ditulis oleh penulis tentang konstruksi algoritmik paling sederhana mendorong algoritma komputasi untuk bot selama berhari-hari dan tidak ada kebocoran memori dan kegagalan lainnya pada beban tinggi. Ini juga berlaku untuk CUDA, pada awalnya tampaknya rumit, tetapi didasarkan pada prinsip-prinsip sederhana dan tentu saja sulit untuk menginisialisasi tempat pada GPU di tempat-tempat jika ada banyak, tetapi kemudian Anda akan memiliki roket kecil Anda sendiri, dengan asap dari kartu video.


Dari kelas objek untuk pelatihan dengan GPU, penulis merekomendasikan automata seluler . Pada suatu waktu ada peningkatan popularitas dan mode untuk mereka, tetapi kemudian jaringan saraf menangkap pikiran para pengembang.
Hingga:


"Setiap kuantitas dalam fisika, termasuk waktu dan ruang, adalah terbatas dan terpisah."
daripada bukan otomat seluler.


Tapi itu indah ketika tiga formula sederhana dapat membuat ini:



Jika akan menarik untuk membaca tentang automata seluler di CUDA, tulis di komentar, akan ada bahan yang diketik untuk artikel kecil.
Dan ini adalah sumber automata seluler (di bawah video ada tautan ke sumbernya):



Gagasan untuk menulis artikel setelah sarapan, dalam satu napas tampaknya bagi saya berhasil. Waktu kopi kedua. Memiliki pembaca akhir pekan yang menyenangkan.

Source: https://habr.com/ru/post/id417757/


All Articles