Ekstensi SIMD ke C ++ OpenMP di Visual Studio

Di era aplikasi AI di mana-mana ada permintaan yang muncul dari compiler mempercepat komputasi-mesin belajar kode intensif untuk perangkat keras yang ada. Kode seperti itu biasanya melakukan perhitungan matematis seperti transformasi dan manipulasi matriks dan biasanya dalam bentuk loop. Perpanjangan SIMD dari OpenMP memberikan pengguna cara yang mudah untuk mempercepat loop dengan secara eksplisit memanfaatkan unit vektor prosesor modern. Kami bangga mulai menawarkan C / C ++ OpenMP SIMD vectorization di Visual Studio 2019.


Antarmuka program aplikasi OpenMP C / C ++ pada awalnya dirancang untuk meningkatkan kinerja aplikasi dengan mengaktifkan kode yang akan dieksekusi secara paralel secara paralel pada beberapa prosesor pada 1990-an. Selama bertahun-tahun standar OpenMP telah diperluas untuk mendukung konsep tambahan seperti paralelisasi berbasis tugas, vektorisasi SIMD, dan pembongkaran prosesor. Sejak 2005, Visual Studio telah mendukung standar OpenMP 2.0 yang berfokus pada paralelisasi multithreaded. Ketika dunia bergerak ke era AI, kami melihat peluang yang berkembang untuk meningkatkan kualitas kode dengan memperluas dukungan standar OpenMP di Visual Studio. Kami melanjutkan perjalanan kami di Visual Studio 2019 dengan menambahkan dukungan untuk OpenMP SIMD.




OpenMP SIMD, pertama kali diperkenalkan dalam standar OpenMP 4.0, terutama menargetkan vektorisasi loop. Sejauh ini fitur OpenMP yang paling banyak digunakan dalam pembelajaran mesin menurut penelitian kami. Dengan menganotasi loop dengan arahan OpenMP SIMD, kompiler dapat mengabaikan dependensi vektor dan membuat vektorisasi loop sebanyak mungkin. Kompiler menghormati niat pengguna untuk menjalankan beberapa perulangan yang dijalankan secara bersamaan.


#pragma omp simd for (i = 0; i < count; i++) { a[i] = b[i] + 1; } 

Seperti yang Anda ketahui, C ++ di Visual Studio sudah menyediakan pragma loop non-OpenMP serupa seperti #pragma vector dan #pragma ivdep . Namun, kompiler dapat berbuat lebih banyak dengan OpenMP SIMD. Sebagai contoh:


  1. Kompilator selalu diizinkan untuk mengabaikan dependensi vektor apa pun yang ada.
  2. / fp: fast diaktifkan di dalam loop.
  3. Loop dengan pemanggilan fungsi adalah vektor.
  4. Lingkaran luar vektor.
  5. Loop bersarang dapat digabung menjadi satu loop dan di-vektor-kan.
  6. Akselerasi hybrid dapat dicapai dengan #pragma omp for simd untuk memungkinkan multithreading berbutir kasar dan vektorisasi berbutir halus.

Selain itu, arahan OpenMP SIMD dapat mengambil klausa berikut untuk lebih meningkatkan vektorisasi:


  • simdlen ( panjang ): tentukan jumlah jalur vektor
  • safelen ( panjang ): tentukan jarak ketergantungan vektor
  • linear ( daftar [ : linear-langkah] ): pemetaan linear dari variabel induksi loop ke langganan array
  • aligned ( list [ : alignment] ): penyelarasan data
  • pribadi ( daftar ): tentukan privatisasi data
  • lastprivate ( daftar ): tentukan privatisasi data dengan nilai akhir dari iterasi terakhir
  • reduksi ( pengurang reduksi : daftar ): tentukan operasi reduksi yang disesuaikan
  • collapse ( n ): coalescing loop nest

-Openmp Baru : sakelar eksperimental


Program beranotasi OpenMP-SIMD dapat dikompilasi dengan saklar CL baru -openmp: eksperimental. Switch baru ini memungkinkan fitur OpenMP tambahan tidak tersedia di bawah -opmp . Sementara nama sakelar ini adalah "eksperimental", sakelar itu sendiri, dan fungsi yang diaktifkan sepenuhnya didukung dan siap produksi. Namanya mencerminkan bahwa itu tidak memungkinkan subset lengkap atau versi standar OpenMP. Iterasi kompiler di masa mendatang dapat menggunakan sakelar ini untuk mengaktifkan fitur OpenMP tambahan dan sakelar terkait OpenMP baru dapat ditambahkan. -Openmp: sakelar eksperimental menggunakan sakelar -openmp yang artinya kompatibel dengan semua fitur OpenMP 2.0. Perhatikan bahwa direktif SIMD dan klausulnya tidak dapat dikompilasi dengan sakelar -openmp .


Untuk loop yang tidak di-vector, compiler akan mengeluarkan pesan untuk masing-masingnya seperti di bawah ini. Misalnya,


cl -O2 -openmp: eksperimental mycode.cpp


mycode.cpp (84): info C5002: Omp simd loop tidak di-vectorized karena alasan '1200'


mycode.cpp (90): info C5002: Omp simd loop tidak di-vectorized karena alasan '1200'


Untuk loop yang di-vektor-kan, kompiler tetap diam kecuali sakelar logging vektorisasi disediakan:


cl -O2 -openmp: eksperimental -Qvec-report: 2 mycode.cpp


mycode.cpp (84): info C5002: Omp simd loop tidak di-vectorized karena alasan '1200'


mycode.cpp (90): info C5002: Omp simd loop tidak di-vectorized karena alasan '1200'


mycode.cpp (96): info C5001: Omp simd loop di-vectorized


Sebagai langkah pertama mendukung OpenMP SIMD, pada dasarnya kami telah menghubungkan pragma SIMD dengan backend vectorizer di bawah saklar baru. Kami fokus pada vektorisasi loop paling dalam dengan meningkatkan vectorizer dan analisis alias. Tidak ada klausa SIMD yang efektif dalam Visual Studio 2019 pada saat penulisan ini. Mereka akan diurai tetapi diabaikan oleh kompiler dengan peringatan yang dikeluarkan untuk kesadaran pengguna. Sebagai contoh, kompiler akan mengeluarkan


peringatan C4849: Klausa 'simdlen' OpenMP diabaikan dalam arahan 'simd'


untuk kode berikut:


 #pragma omp simd simdlen(8) for (i = 1; i < count; i++) { a[i] = a[i-1] + 1; b[i] = *c + 1; bar(i); } 

Lebih lanjut tentang semantik arahan OpenMP SIMD


Arahan OpenMP SIMD memberikan pengguna cara untuk mendikte kompiler untuk membuat vektor loop. Kompiler diizinkan untuk mengabaikan legalitas yang tampak dari vektorisasi tersebut dengan menerima janji kebenaran dari pengguna. Ini adalah tanggung jawab pengguna ketika perilaku tak terduga terjadi dengan vektorisasi. Dengan menganotasi loop dengan arahan OpenMP SIMD, pengguna berniat untuk menjalankan beberapa iterasi loop secara bersamaan. Ini memberi kompiler banyak kebebasan untuk menghasilkan kode mesin yang memanfaatkan sumber daya SIMD atau vektor pada prosesor target. Sementara kompiler tidak bertanggung jawab untuk mengeksplorasi kebenaran dan keuntungan paralelisme yang ditentukan pengguna tersebut, ia masih harus memastikan perilaku berurutan dari satu iterasi loop tunggal.


Sebagai contoh, loop berikut dijelaskan dengan arahan OpenMP SIMD. Tidak ada paralelisme sempurna di antara iterasi loop karena ada ketergantungan ke belakang dari [i] ke [i-1]. Tetapi karena direktif SIMD kompiler masih diperbolehkan untuk mengemas iterasi berturut-turut dari pernyataan pertama ke dalam satu instruksi vektor dan menjalankannya secara paralel.


 #pragma omp simd for (i = 1; i < count; i++) { a[i] = a[i-1] + 1; b[i] = *c + 1; bar(i); } 

Oleh karena itu, bentuk vektor yang ditransformasikan berikut dari loop adalah legal karena kompiler menjaga perilaku berurutan dari setiap iterasi loop asli. Dengan kata lain, [i] dieksekusi setelah [-1], b [i] setelah [i] dan panggilan ke bilah akhirnya terjadi.


 #pragma omp simd for (i = 1; i < count; i+=4) { a[i:i+3] = a[i-1:i+2] + 1; b[i:i+3] = *c + 1; bar(i); bar(i+1); bar(i+2); bar(i+3); } 

Adalah ilegal untuk memindahkan referensi memori * c dari loop jika mungkin alias dengan [i] atau b [i] . Juga ilegal untuk menyusun ulang pernyataan di dalam satu iterasi asli jika melanggar ketergantungan berurutan. Sebagai contoh, loop yang diubah berikut ini tidak sah.


 c = b; t = *c; #pragma omp simd for (i = 1; i < count; i+=4) { a[i:i+3] = a[i-1:i+2] + 1; bar(i); // illegal to reorder if bar[i] depends on b[i] b[i:i+3] = t + 1; // illegal to move *c out of the loop bar(i+1); bar(i+2); bar(i+3); } 

Rencana dan Umpan Balik di masa depan


Kami mendorong Anda untuk mencoba fitur baru ini. Seperti biasa, kami menyambut umpan balik Anda. Jika Anda melihat loop SIMP OpenMP yang Anda harapkan menjadi vektor, tetapi tidak atau kode yang dihasilkan tidak optimal, beri tahu kami. Kami dapat dihubungi melalui komentar di bawah ini, melalui email ( visualcpp@microsoft.com ), twitter (@visualc), atau melalui Komunitas Pengembang .


Ke depan, kami senang mendengar kebutuhan Anda akan fungsionalitas OpenMP yang hilang di Visual Studio. Karena ada beberapa evolusi besar dalam OpenMP sejak standar 2.0, OpenMP sekarang memiliki fitur luar biasa untuk memudahkan usaha Anda membangun program berkinerja tinggi. Misalnya, pemrograman konkurensi berbasis tugas tersedia mulai dari OpenMP 3.0. Komputasi heterogen (CPU + akselerator) didukung dalam OpenMP 4.0. Vektorisasi SIMD lanjutan dan dukungan paralelisasi loop DOACROSS juga tersedia dalam standar OpenMP terbaru sekarang. Silakan periksa revisi standar lengkap dan set fitur dari situs web resmi OpenMP: https://www.openmp.org . Kami dengan tulus meminta pendapat Anda tentang fitur OpenMP spesifik yang ingin Anda lihat. Kami juga tertarik mendengar tentang bagaimana Anda menggunakan OpenMP untuk mempercepat kode Anda. Umpan balik Anda sangat penting karena akan membantu mengarahkan arahan dukungan OpenMP di Visual Studio.


Avatar
Hongtao Yu

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


All Articles