सबसे पहले, आपको इस तथ्य के बारे में पता होना चाहिए कि CUDA स्वचालित रूप से कम्प्यूटेशन को तेज नहीं करेगा। एक तरफ, क्योंकि GPU प्रोग्रामिंग एक कला है, और यह बहुत ही सही हो सकता है, इसे सही करने के लिए बहुत चुनौतीपूर्ण है । दूसरी ओर, क्योंकि केवल कुछ प्रकार की संगणनाओं के लिए जीपीयू अच्छी तरह से अनुकूल हैं ।
यह भ्रामक लग सकता है, क्योंकि आप मूल रूप से GPU पर कुछ भी गणना कर सकते हैं । प्रमुख बिंदु, निश्चित रूप से, आप एक अच्छा स्पीडअप प्राप्त करेंगे या नहीं। यहां सबसे महत्वपूर्ण वर्गीकरण यह है कि क्या कोई समस्या कार्य समानांतर या डेटा समानांतर है । पहले एक को संदर्भित करता है, मोटे तौर पर समस्याओं के लिए, जहां कई धागे अपने स्वयं के कार्यों पर काम कर रहे हैं, कम या ज्यादा स्वतंत्र रूप से। दूसरा एक समस्याओं को संदर्भित करता है जहां कई धागे सभी एक ही कर रहे हैं - लेकिन डेटा के विभिन्न भागों पर।
उत्तरार्द्ध इस तरह की समस्या है कि जीपीयू अच्छे हैं: उनके पास कई कोर हैं, और सभी कोर ऐसा ही करते हैं, लेकिन इनपुट डेटा के विभिन्न हिस्सों पर काम करते हैं।
आपने उल्लेख किया है कि आपके पास "सरल गणित है लेकिन भारी मात्रा में डेटा है"। हालांकि यह पूरी तरह से डेटा-समानांतर समस्या की तरह लग सकता है और इस तरह यह एक GPU के लिए अच्छी तरह से अनुकूल था, इस पर विचार करने के लिए एक और पहलू है: सैद्धांतिक कम्प्यूटेशनल पावर (FLOPS, फ़्लोटिंग पॉइंट ऑपरेशंस प्रति सेकंड) के मामले में GPU हास्यास्पद रूप से तेज़ हैं। लेकिन वे अक्सर मेमोरी बैंडविड्थ से नीचे गिर जाते हैं।
इससे समस्याओं का एक और वर्गीकरण होता है। अर्थात् क्या समस्याएँ स्मृति बद्ध हैं या बाध्य बाध्य हैं ।
पहला एक समस्याओं को संदर्भित करता है जहां प्रत्येक डेटा तत्व के लिए किए जाने वाले निर्देशों की संख्या कम है। उदाहरण के लिए, एक समानांतर वेक्टर जोड़ पर विचार करें: आपको दो डेटा तत्वों को पढ़ना होगा , फिर एक एकल प्रदर्शन करना होगा, और फिर परिणाम वेक्टर में योग लिखना होगा। जीपीयू पर ऐसा करते समय आपको स्पीडअप दिखाई नहीं देगा, क्योंकि एकल जोड़ मेमोरी पढ़ने / लिखने के प्रयासों की भरपाई नहीं करता है।
दूसरा शब्द, "कंप्यूट बाउंड", उन समस्याओं को संदर्भित करता है जहां निर्देशों की संख्या मेमोरी रीड / राइट की संख्या की तुलना में अधिक है। उदाहरण के लिए, एक मैट्रिक्स गुणन पर विचार करें: जब मैट्रिक्स का आकार n होता है, तो निर्देशों की संख्या O (n ^ 3) होगी। इस मामले में, कोई भी उम्मीद कर सकता है कि GPU एक निश्चित मैट्रिक्स आकार में सीपीयू से बेहतर प्रदर्शन करेगा। एक और उदाहरण तब हो सकता है जब कई जटिल त्रिकोणमितीय संगणनाएँ (साइन / कोसाइन आदि) "कुछ" डेटा तत्वों पर की जाती हैं।
अंगूठे के एक नियम के रूप में: आप मान सकते हैं कि "मुख्य" जीपीयू मेमोरी से एक डेटा तत्व को पढ़ने / लिखने में लगभग 500 मिलियन की विलंबता है।
इसलिए, GPUs के प्रदर्शन के लिए एक और महत्वपूर्ण बिंदु डेटा स्थानीयता है : यदि आपको डेटा पढ़ना है या लिखना है (और ज्यादातर मामलों में, आपको; ;-)) करना होगा, तो आपको यह सुनिश्चित करना चाहिए कि डेटा उतना ही पास रखा जाए। GPU कोर के लिए संभव है। जीपीयू में कुछ मेमोरी क्षेत्र होते हैं ("स्थानीय मेमोरी" या "साझा मेमोरी" के रूप में संदर्भित) जो आमतौर पर केवल कुछ केबी आकार का होता है, लेकिन डेटा के लिए विशेष रूप से कुशल है जो एक संगणना में शामिल होने वाला है।
इसलिए इसे फिर से जोर देने के लिए: GPU प्रोग्रामिंग एक कला है, जो केवल CPU पर समानांतर प्रोग्रामिंग से संबंधित है। जावा में थ्रेड्स जैसी चीजें, जैसे कि सभी कंसिस्टेंसी इन्फ्रास्ट्रक्चर के साथ ThreadPoolExecutors
, ForkJoinPools
आदि यह धारणा दे सकते हैं कि आपको अपने काम को किसी तरह विभाजित करना होगा और इसे कई प्रोसेसर के बीच वितरित करना होगा। GPU पर, आप बहुत निचले स्तर पर चुनौतियों का सामना कर सकते हैं: व्यवसाय, रजिस्टर दबाव, साझा स्मृति दबाव, मेमोरी coalescing ... बस कुछ ही नाम करने के लिए।
हालाँकि, जब आपके पास हल करने के लिए डेटा-समानांतर, कंप्यूट-बाउंड समस्या है, तो GPU जाने का रास्ता है।
एक सामान्य टिप्पणी: आपका विशेष रूप से CUDA के लिए कहा गया है। लेकिन मैं दृढ़ता से आपको OpenCL पर एक नज़र डालने की सलाह दूंगा। इसके कई फायदे हैं। सबसे पहले, यह एक विक्रेता-स्वतंत्र, खुले उद्योग मानक है, और AMD, Apple, Intel और NVIDIA द्वारा OpenCL के कार्यान्वयन हैं। इसके अतिरिक्त, जावा दुनिया में ओपनसीएल के लिए बहुत व्यापक समर्थन है। एकमात्र मामला जहां मैं CUDA के लिए समझौता करूँगा, जब आप CUDA रनटाइम लाइब्रेरीज़ का उपयोग करना चाहते हैं, जैसे BLFT (मैट्रिक्स / वेक्टर ऑपरेशन) के लिए FFT या CUBLAS के लिए CUFFT। यद्यपि ओपनसीएल के लिए समान पुस्तकालय प्रदान करने के लिए दृष्टिकोण हैं, उन्हें सीधे जावा की ओर से उपयोग नहीं किया जा सकता है, जब तक कि आप इन पुस्तकालयों के लिए अपने स्वयं के जेएनआई बाइंडिंग नहीं बनाते हैं।
आपको यह सुनना भी दिलचस्प लग सकता है कि अक्टूबर 2012 में, OpenJDK हॉटस्पॉट समूह ने "सुमात्रा": http://openjdk.java.net/projects/sumatra/ परियोजना शुरू की । इस परियोजना का लक्ष्य JVM में सीधे JIT के समर्थन के साथ GPU सहायता प्रदान करना है । वर्तमान स्थिति और प्रथम परिणाम http://mail.openjdk.java.net/mailman/listinfo/sumatra-dev पर उनकी मेलिंग सूची में देखे जा सकते हैं
हालांकि, कुछ समय पहले, मैंने "जावा पर जीपीयू" से संबंधित कुछ संसाधनों को सामान्य रूप से एकत्र किया था। मैं इन्हें फिर से यहाँ प्रस्तुत करूँगा, किसी विशेष क्रम में नहीं।
( अस्वीकरण : मैं http://jcuda.org/ और http://jocl.org/ का लेखक हूं )
(बाइट) कोड अनुवाद और OpenCL कोड पीढ़ी:
https://github.com/aparapi/aparapi : एक ओपन-सोर्स लाइब्रेरी है जो AMD द्वारा सक्रिय रूप से बनाई और बनाई जाती है। एक विशेष "कर्नेल" वर्ग में, एक विशिष्ट विधि को ओवरराइड कर सकता है जिसे समानांतर में निष्पादित किया जाना चाहिए। इस विधि के बाइट कोड को रन-टाइम पर खुद के बाइटकोड रीडर का उपयोग करके लोड किया जाता है। कोड को OpenCL कोड में अनुवादित किया जाता है, जिसे बाद में OpenCL संकलक का उपयोग करके संकलित किया जाता है। परिणाम को फिर OpenCL डिवाइस पर निष्पादित किया जा सकता है, जो कि GPU या CPU हो सकता है। यदि OpenCL में संकलन संभव नहीं है (या OpenCL उपलब्ध नहीं है), तो थ्रेड पूल का उपयोग करते हुए, कोड को अभी भी समानांतर में निष्पादित किया जाएगा।
https://github.com/pcpratts/rootbeer1 : जावा के कुछ हिस्सों को CUDA कार्यक्रमों में परिवर्तित करने के लिए एक ओपन-सोर्स लाइब्रेरी। यह समर्पित इंटरफेस प्रदान करता है जो यह इंगित करने के लिए लागू किए जा सकते हैं कि एक निश्चित वर्ग को GPU पर निष्पादित किया जाना चाहिए। Aparapi के विपरीत, यह स्वचालित रूप से "प्रासंगिक" डेटा (यानी, ऑब्जेक्ट ग्राफ का पूरा प्रासंगिक हिस्सा!) एक प्रतिनिधित्व में प्रस्तुत करता है जो GPU के लिए उपयुक्त है।
https : // code। लाइब्रेरी को पीएचडी थीसिस के संदर्भ में विकसित किया गया था, जिसमें अनुवाद प्रक्रिया के बारे में गहन पृष्ठभूमि की जानकारी है।
https://github.com/ochafik/ScalaCL : OpenCL के लिए स्लैब बाइंडिंग। ओपनसीएल के साथ समानांतर में विशेष स्काला संग्रह को संसाधित करने की अनुमति देता है। संग्रह के तत्वों पर कहे जाने वाले फ़ंक्शंस सामान्य रूप से स्काला फ़ंक्शंस (कुछ सीमाओं के साथ) हो सकते हैं जो तब ओपनसीएल कर्नेल में अनुवादित होते हैं।
भाषा एक्सटेंशन
http://www.ateji.com/px/index.html : जावा के लिए एक भाषा विस्तार जो समानांतर निर्माण (जैसे छोरों के लिए समानांतर, ओपनएमपी शैली) की अनुमति देता है जो तब ओपनसीएल के साथ GPU पर निष्पादित होते हैं। दुर्भाग्य से, यह बहुत आशाजनक परियोजना नहीं रह गई है।
http://www.habanero.rice.edu/Publications.html (JCUDA): एक पुस्तकालय जो विशेष जावा कोड (जिसे JCUDA कोड कहा जाता है) को Java- और CUDA-C कोड में अनुवाद कर सकता है, जिसे बाद में संकलित और निष्पादित किया जा सकता है। GPU। हालाँकि, लाइब्रेरी सार्वजनिक रूप से उपलब्ध नहीं है।
https://www2.informatik.uni-erlangen.de/EN/research/JavaOpenMP/index.html : OpenMP के निर्माण के लिए जावा भाषा का विस्तार, CUDA बैकएंड के साथ
Java OpenCL / CUDA बाइंडिंग लाइब्रेरी
https://github.com/ochafik/JavaCL : जावा ओपनसीएल के लिए बाइंडिंग: एक ऑब्जेक्ट-ओरिएंटेड ओपनसीएल लाइब्रेरी, ऑटो-जेनरेट किए गए निम्न-स्तरीय बाइंडिंग पर आधारित है।
http://jogamp.org/jocl/www/ : OpenCL के लिए जावा बाइंडिंग: ऑटो-जनरेट किए गए निम्न-स्तरीय बाइंडिंग के आधार पर ऑब्जेक्ट-ओरिएंटेड OpenCL लाइब्रेरी
http://www.lwjgl.org/ : OpenCL के लिए जावा बाइंडिंग: ऑटो-जेनरेट किए गए निम्न-स्तरीय बाइंडिंग और ऑब्जेक्ट-ओरिएंटेड सुविधा वर्ग
http://jocl.org/ : OpenCL के लिए जावा बाइंडिंग: निम्न स्तर के बाइंडिंग जो मूल OpenCL API की 1: 1 मैपिंग हैं
http://jcuda.org/ : CUDA के लिए जावा बाइंडिंग: निम्न स्तर के बाइंडिंग जो मूल CUDA API की 1: 1 मैपिंग हैं
विविध
http://sourceforge.net/projects/jopencl/ : OpenCL के लिए जावा बाइंडिंग। 2010 के बाद से इसका रखरखाव नहीं किया जा रहा है
http://www.hoopoe-cloud.com/ : CUDA के लिए जावा बाइंडिंग। अब बनाए रखने के लिए नहीं लगता है