Bagaimana CUDA dan OpenCL dibandingkan satu sama lain pada akhir 2013 dari perspektif programmer? Grup saya sedang berpikir tentang mencoba memanfaatkan komputasi GPU. Apakah kita akan membatasi diri kita secara signifikan dengan memilih perangkat keras yang hanya mendukung OpenCL tetapi tidak CUDA?
Untuk menjadi sedikit lebih spesifik, apakah asumsi berikut ini benar?
Segala sesuatu yang mungkin di CUDA juga dimungkinkan di OpenCL
Selama kita tidak menggunakan perpustakaan, tugas yang diberikan tidak secara signifikan lebih mudah (atau lebih sulit) untuk dilakukan di salah satu dari mereka
Keuntungan utama CUDA adalah ketersediaan perpustakaan
Keduanya memiliki dukungan yang baik untuk ketiga platform utama (Win / OSX / Linux)
Jawaban:
Saya akan mencoba merangkum pengalaman saya yang didapat dalam pengembangan ViennaCL, di mana kami memiliki backend CUDA dan OpenCL dengan kebanyakan terjemahan 1: 1 dari banyak kernel komputasi. Dari pertanyaan Anda, saya juga akan berasumsi bahwa kita sebagian besar menggunakan GPU di sini.
Portabilitas Kinerja.Pertama-tama, tidak ada yang namanya kernel portable-performance dalam arti bahwa Anda menulis kernel sekali dan itu akan berjalan secara efisien pada setiap perangkat keras. Tidak di OpenCL, di mana lebih jelas karena jangkauan perangkat keras yang lebih luas yang didukung, tetapi juga tidak di CUDA. Dalam CUDA itu kurang jelas karena jangkauan perangkat keras yang lebih kecil, tetapi bahkan di sini kita harus membedakan setidaknya tiga arsitektur perangkat keras (pra-Fermi, Fermi, Kepler) sudah. Fluktuasi kinerja ini dapat dengan mudah menghasilkan variasi kinerja 20 persen tergantung pada bagaimana Anda mengatur utas dan ukuran kelompok kerja mana yang Anda pilih, bahkan jika kernelnya sesederhana salinan penyangga. Mungkin juga perlu disebutkan bahwa pada GPU pra-Fermi dan Fermi dimungkinkan untuk menulis kernel multiplikasi matriks-matriks cepat langsung di CUDA, sementara untuk GPU Kepler terbaru, tampaknya seseorang harus turun ke bahasa pseudo-assembly PTX untuk mendekati kinerja CUBLAS. Dengan demikian, bahkan bahasa yang dikontrol vendor seperti CUDA tampaknya memiliki masalah untuk mengimbangi perkembangan perangkat keras. Selain itu, semua kode CUDA dikompilasi secara statis ketika Anda menjalankan nvcc, yang agak membutuhkan tindakan penyeimbangan melalui flag -arch, sementara kernel OpenCL dikompilasi pada saat run-time dari kompilator just-in-time, sehingga Anda pada prinsipnya dapat menyesuaikan kernel ke spesifik perangkat komputasi tertentu. Yang terakhir, bagaimanapun, cukup terlibat dan biasanya hanya menjadi pilihan yang sangat menarik ketika kode Anda matang dan ketika pengalaman Anda menumpuk. Harga yang harus dibayar adalah waktu O (1) yang diperlukan untuk kompilasi just-in-time, yang dapat menjadi masalah dalam situasi tertentu. OpenCL 2.
Debugging dan Profiling. Alat debugging dan profil CUDA adalah yang terbaik yang tersedia untuk GPGPU. Perangkat AMD juga tidak buruk, tetapi mereka tidak termasuk permata seperti cuda-gdb atau cuda-memcheck. Juga, masih hari ini NVIDIA menyediakan driver dan SDK yang paling kuat untuk GPGPU, sistem macet karena kernel kereta adalah pengecualian, bukan aturannya, baik dengan OpenCL dan CUDA. Untuk alasan yang saya mungkin tidak perlu jelaskan di sini, NVIDIA tidak lagi menawarkan debugging dan profil untuk OpenCL dengan CUDA 5.0 ke atas.
Aksesibilitas dan Kenyamanan. Jauh lebih mudah untuk mendapatkan dan menjalankan kode CUDA pertama, terutama karena kode CUDA terintegrasi dengan baik dengan kode host. (Saya akan membahas harga yang harus dibayar nanti.) Ada banyak tutorial di web serta panduan pengoptimalan dan beberapa perpustakaan. Dengan OpenCL Anda harus melalui sedikit kode inisialisasi dan menulis kernel Anda dalam string, sehingga Anda hanya menemukan kesalahan kompilasi selama eksekusi ketika memberi makan sumber ke jit-compiler. Karenanya, dibutuhkan waktu lebih lama untuk melalui satu siklus kode / kompilasi / debug dengan OpenCL, sehingga produktivitas Anda biasanya lebih rendah selama tahap pengembangan awal ini.
Aspek Pustaka Perangkat Lunak. Sementara item sebelumnya mendukung CUDA, integrasi ke dalam perangkat lunak lain merupakan nilai tambah besar untuk OpenCL. Anda dapat menggunakan OpenCL dengan hanya menautkan dengan pustaka OpenCL yang dibagikan dan hanya itu, sementara dengan CUDA Anda harus memiliki seluruh rantai alat CUDA tersedia. Lebih buruk lagi, Anda perlu menggunakan kompiler host yang benar agar nvcc dapat berfungsi. Jika Anda pernah mencoba menggunakan mis. CUDA 4.2 dengan GCC 4.6 atau yang lebih baru, Anda akan kesulitan untuk menyelesaikannya. Secara umum, jika Anda memiliki kompiler yang digunakan yang lebih baru daripada CUDA SDK, masalah mungkin terjadi. Integrasi ke dalam sistem build seperti CMake adalah sumber sakit kepala lainnya (Anda juga dapat menemukan banyak bukti tentang misalnya PETScDaftar surat). Ini mungkin bukan masalah pada mesin Anda sendiri di mana Anda memiliki kontrol penuh, tetapi segera setelah Anda mendistribusikan kode Anda, Anda akan mengalami situasi di mana pengguna agak dibatasi dalam tumpukan perangkat lunak mereka. Dengan kata lain, dengan CUDA Anda tidak lagi bebas memilih kompiler host favorit Anda, tetapi NVIDIA menentukan kompiler mana yang diizinkan untuk Anda gunakan.
Aspek Lainnya. CUDA sedikit lebih dekat dengan perangkat keras (misalnya warps), tetapi pengalaman saya dengan aljabar linier adalah bahwa Anda jarang mendapatkan manfaat yang signifikan darinya. Ada beberapa perpustakaan perangkat lunak lebih banyak di luar sana untuk CUDA, tetapi semakin banyak perpustakaan menggunakan beberapa backend komputasi. ViennaCL , VexCL , atau Paralution semua mendukung OpenCL dan CUDA backend sementara itu, tren yang sama dapat dilihat dengan perpustakaan di daerah lain.
GPGPU bukan Peluru Perak. GPGPU telah terbukti memberikan kinerja yang baik untuk operasi terstruktur dan tugas komputasi terbatas. Namun, untuk algoritma dengan bagian pemrosesan sekuensial yang tidak dapat diabaikan, GPGPU tidak dapat secara ajaib mengatasi Hukum Amdahl . Dalam situasi seperti itu Anda lebih baik menggunakan implementasi CPU yang baik dari algoritma terbaik yang tersedia daripada mencoba untuk melempar algoritma yang paralel, tetapi kurang cocok untuk masalah Anda. Juga, PCI-Express adalah hambatan yang serius, jadi Anda perlu memeriksa terlebih dahulu apakah penghematan dari GPU dapat mengkompensasi overhead dari data yang bergerak bolak-balik.
Rekomendasi saya. Silakan pertimbangkan CUDA dan OpenCL daripada CUDA atauOpenCL. Tidak perlu membatasi diri Anda pada satu platform, tetapi mengambil yang terbaik dari kedua dunia. Apa yang bekerja dengan baik bagi saya adalah untuk mengatur implementasi awal dalam CUDA, debug itu, profil itu, dan kemudian port ke OpenCL oleh penggantian string sederhana. (Anda bahkan dapat parametrize rutinitas pembuatan string kernel OpenCL Anda sehingga Anda memiliki fleksibilitas dalam menyetel ke perangkat keras target.) Upaya porting ini biasanya akan menghabiskan kurang dari 10 persen dari waktu Anda, tetapi memberi Anda kemampuan untuk berjalan pada perangkat keras lain juga. Anda mungkin terkejut tentang seberapa baik kinerja perangkat keras non-NVIDIA dalam situasi tertentu. Yang terpenting, pertimbangkan penggunaan kembali fungsionalitas di perpustakaan sejauh mungkin. Sementara cepat & implementasi ulang yang kotor dari beberapa fungsi sering kali dapat diterima untuk eksekusi single-threaded pada CPU, ini akan sering memberi Anda kinerja yang buruk pada perangkat keras paralel besar-besaran. Idealnya Anda bahkan dapat membongkar semuanya ke perpustakaan dan tidak perlu peduli apakah mereka menggunakan CUDA, OpenCL, atau keduanya secara internal. Secara pribadi saya tidak akan pernah berani menulis kode yang dikunci vendor untuk sesuatu yang ingin saya andalkan dalam beberapa tahun dari sekarang, tetapi aspek ideologis ini harus masuk ke diskusi terpisah.
sumber