Katakanlah hambatan program Java saya sebenarnya adalah beberapa loop ketat untuk menghitung sekumpulan produk titik vektor. Ya, saya telah membuat profil, ya itu hambatannya, ya itu signifikan, ya begitulah algoritmanya, ya saya telah menjalankan Proguard untuk mengoptimalkan kode byte, dll.
Karya tersebut, pada dasarnya, adalah produk titik. Seperti, saya memiliki dua float[50]
dan saya perlu menghitung jumlah produk berpasangan. Saya tahu set instruksi prosesor ada untuk melakukan operasi semacam ini dengan cepat dan dalam jumlah besar, seperti SSE atau MMX.
Ya, saya mungkin dapat mengaksesnya dengan menulis beberapa kode asli di JNI. Telepon JNI ternyata cukup mahal.
Saya tahu Anda tidak dapat menjamin JIT akan dikompilasi atau tidak. Adakah yang pernah mendengar tentang kode yang menghasilkan JIT yang menggunakan instruksi ini? dan jika demikian, apakah ada sesuatu tentang kode Java yang membantu membuatnya dapat dikompilasi dengan cara ini?
Mungkin "tidak"; layak untuk ditanyakan.
sumber
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:+LogCompilation
. Anda memerlukan program yang menjalankan metode vectorizable cukup sering untuk membuatnya "panas".Jawaban:
Jadi, pada dasarnya, Anda ingin kode Anda berjalan lebih cepat. JNI adalah jawabannya. Saya tahu Anda mengatakan itu tidak berhasil untuk Anda, tetapi izinkan saya menunjukkan kepada Anda bahwa Anda salah.
Berikut ini
Dot.java
:dan
Dot.h
:Kita dapat mengkompilasi dan menjalankannya dengan JavaCPP menggunakan perintah ini:
Dengan CPU Intel (R) Core (TM) i7-7700HQ @ 2.80GHz, Fedora 30, GCC 9.1.1, dan OpenJDK 8 atau 11, saya mendapatkan output semacam ini:
Atau kira-kira 2,4 kali lebih cepat. Kita perlu menggunakan buffer NIO langsung daripada array, tetapi HotSpot dapat mengakses buffer NIO langsung secepat array . Di sisi lain, membuka loop secara manual tidak memberikan peningkatan kinerja yang terukur, dalam kasus ini.
sumber
Untuk mengatasi beberapa skeptisisme yang diungkapkan oleh orang lain di sini, saya menyarankan siapa pun yang ingin membuktikan kepada diri sendiri atau orang lain menggunakan metode berikut:
Contoh:
Hasil dengan dan tanpa flag (pada laptop Haswell terbaru, Oracle JDK 8u60): -XX: + UseSuperWord: 475.073 ± 44.579 ns / op (nanodetik per op) -XX: -UseSuperWord: 3376.364 ± 233.211 ns / op
Perakitan untuk hot loop agak banyak untuk memformat dan menempel di sini tetapi ini cuplikannya (hsdis.so gagal memformat beberapa instruksi vektor AVX2 jadi saya menjalankan dengan -XX: UseAVX = 1): -XX: + UseSuperWord (dengan '-prof perfasm: intelSyntax = true')
Selamat bersenang-senang menyerbu kastil!
sumber
Dalam versi HotSpot yang dimulai dengan Java 7u40, kompiler server menyediakan dukungan untuk vektorisasi otomatis. Menurut JDK-6340864
Namun, ini tampaknya benar hanya untuk "loop sederhana" - setidaknya untuk saat ini. Misalnya, mengumpulkan sebuah array belum dapat di-vektorisasi JDK-7192383
sumber
Berikut adalah artikel bagus tentang bereksperimen dengan Java dan instruksi SIMD yang ditulis oleh teman saya: http://prestodb.rocks/code/simd/
Hasil umumnya adalah Anda dapat mengharapkan JIT menggunakan beberapa operasi SSE di 1.8 (dan beberapa lagi di 1.9). Padahal Anda seharusnya tidak berharap banyak dan Anda perlu berhati-hati.
sumber
Anda dapat menulis kernel OpenCl untuk melakukan komputasi dan menjalankannya dari java http://www.jocl.org/ .
Kode dapat dijalankan pada CPU dan / atau GPU dan bahasa OpenCL juga mendukung jenis vektor sehingga Anda harus dapat memanfaatkan secara eksplisit misalnya instruksi SSE3 / 4.
sumber
Lihat perbandingan Performa antara Java dan JNI untuk implementasi yang optimal dari kernel mikro komputasi . Mereka menunjukkan bahwa kompiler server Java HotSpot VM mendukung vektorisasi otomatis menggunakan Super-word Level Parallelism, yang terbatas pada kasus sederhana di dalam paralelisme loop. Artikel ini juga akan memberi Anda beberapa panduan apakah ukuran data Anda cukup besar untuk membenarkan penggunaan rute JNI.
sumber
Saya menduga Anda telah menulis pertanyaan ini sebelum Anda mengetahui tentang netlib-java ;-) menyediakan persis API asli yang Anda butuhkan, dengan implementasi yang dioptimalkan mesin, dan tidak memiliki biaya apa pun di batas asli karena berkat penyematan memori.
sumber
Saya tidak percaya sebagian besar jika ada VM yang cukup pintar untuk pengoptimalan semacam ini. Agar adil, sebagian besar pengoptimalan jauh lebih sederhana, seperti menggeser alih-alih perkalian saat pangkat dua. Proyek mono memperkenalkan vektor mereka sendiri dan metode lain dengan dukungan asli untuk membantu kinerja.
sumber