AI टूल्स 101

CUDA को मास्टर करें: मशीन लर्निंग इंजीनियर्स के लिए

mm
Unite.AI को Google पर अपने पसंदीदा स्रोतों में जोड़ें
Master CUDA: For Machine Learning Engineers
div]:bg-bg-300 [&_pre]:-mr-4 md:[&_pre]:-mr-9″>

गणना शक्ति मशीन लर्निंग में संभव की सीमाओं को बढ़ाने में एक महत्वपूर्ण कारक बन गई है। जैसे ही मॉडल अधिक जटिल होते जाते हैं और डेटासेट एक्सपोनेंशियल रूप से बढ़ते हैं, पारंपरिक सीपीयू-आधारित कंप्यूटिंग अक्सर आधुनिक मशीन लर्निंग कार्यों की मांगों को पूरा करने में कम पड़ जाती है। यहीं पर CUDA (कंप्यूट यूनिफाइड डिवाइस आर्किटेक्चर) आता है, जो मशीन लर्निंग वर्कफ्लो को तेज करने के लिए एक दृष्टिकोण है।

CUDA, NVIDIA (NVDA ) द्वारा विकसित, एक समानांतर कंप्यूटिंग प्लेटफ़ॉर्म और प्रोग्रामिंग मॉडल है जो ग्राफिक्स प्रोसेसिंग यूनिट्स (जीपीयू) की विशाल गणना शक्ति का लाभ उठाता है। जबकि जीपीयू मूल रूप से ग्राफिक्स रेंडरिंग के लिए डिज़ाइन किए गए थे, उनका आर्किटेक्चर उन्हें कई मशीन लर्निंग एल्गोरिदम की समानांतर प्रोसेसिंग आवश्यकताओं के लिए असाधारण रूप से उपयुक्त बनाता है।

इस लेख में, हम देखेंगे कि CUDA आपके मशीन लर्निंग परियोजनाओं को कैसे क्रांतिकारी बना सकता है, इसके मूल अवधारणाओं, आर्किटेक्चर और व्यावहारिक अनुप्रयोगों में गोता लगाते हुए। चाहे आप एक अनुभवी एमएल इंजीनियर हों जो अपने वर्कफ्लो को अनुकूलित करना चाहते हैं या एक नए जो जीपीयू कंप्यूटिंग की शक्ति का दोहन करने के लिए उत्सुक हैं, यह गाइड आपको अपने मशीन लर्निंग प्रयासों को अगले स्तर पर ले जाने के लिए ज्ञान से लैस करेगा।

समानांतर कंप्यूटिंग और CUDA को समझना

CUDA के विशिष्ट विवरण से पहले समानांतर कंप्यूटिंग की मूल अवधारणा को समझना आवश्यक है। मूल रूप से, समानांतर कंप्यूटिंग एक गणना का रूप है जहां कई गणनाएं एक साथ की जाती हैं। सिद्धांत सरल लेकिन शक्तिशाली है: बड़ी समस्याओं को अक्सर छोटी समस्याओं में विभाजित किया जा सकता है, जो तब समानांतर में हल की जाती हैं।

पारंपरिक अनुक्रमिक प्रोग्रामिंग, जहां कार्य एक के बाद एक किए जाते हैं, एक हाईवे की एक लेन के समान हो सकती है। समानांतर कंप्यूटिंग, दूसरी ओर, उस हाईवे पर कई लेन जोड़ने जैसा है, जिससे अधिक यातायात (या हमारे मामले में, गणना) एक साथ प्रवाहित हो सकता है।

CUDA इस अवधारणा को लेता है और इसे जीपीयू की विशिष्ट आर्किटेक्चर पर लागू करता है। सीपीयू के विपरीत, जो विभिन्न कार्यों को संभालने के लिए जटिल नियंत्रण तर्क के साथ डिज़ाइन किए गए हैं, जीपीयू समान, सरल ऑपरेशन को समानांतर में करने के लिए अनुकूलित होते हैं। यह उन्हें मशीन लर्निंग में सामान्य गणनाओं के लिए आदर्श बनाता है, जैसे कि मैट्रिक्स गुणा और संयोजन।

आइए कुछ मुख्य अवधारणाओं को तोड़ दें:

  1. थ्रेड्स और थ्रेड हायरार्की

CUDA में, एक थ्रेड निष्पादन की सबसे छोटी इकाई है। सीपीयू थ्रेड्स के विपरीत, जो अपेक्षाकृत भारी होते हैं, जीपीयू थ्रेड्स बहुत हल्के होते हैं। एक典型 CUDA प्रोग्राम हजारों या甚至 लाखों थ्रेड्स को एक साथ लॉन्च कर सकता है।

CUDA थ्रेड्स को एक हायरार्की में व्यवस्थित करता है:

  • थ्रेड्स को ब्लॉक्स में समूहीकृत किया जाता है
  • ब्लॉक्स को एक ग्रिड में व्यवस्थित किया जाता है

यह संरचनात्मक संरचना विभिन्न जीपीयू आर्किटेक्चर में कुशलता से स्केलिंग की अनुमति देती है। यहाँ एक सरल दृश्य है:


<p>|-- Block (0,0)
| |-- Thread (0,0)
| |-- Thread (0,1)
| |-- ...
|-- Block (0,1)
| |-- Thread (0,0)
| |-- Thread (0,1)
| |-- ...
|-- ...
  1. मेमोरी हायरार्की

CUDA विभिन्न प्रकार की मेमोरी प्रदान करता है, प्रत्येक की अपनी विशेषताएं हैं:

  • ग्लोबल मेमोरी: सभी थ्रेड्स द्वारा एक्सेस की जा सकती है, लेकिन उच्च लेटेंसी के साथ
  • शेयर्ड मेमोरी: ब्लॉक के भीतर थ्रेड्स के बीच साझा की जाने वाली तेज मेमोरी
  • लोकल मेमोरी: प्रत्येक थ्रेड के लिए विशिष्ट
  • कॉन्स्टेंट मेमोरी: केवल-पढ़ने वाली मेमोरी निरंतर डेटा के लिए

CUDA प्रोग्राम्स को अनुकूलित करने के लिए इस मेमोरी हायरार्की को समझना और प्रभावी ढंग से उपयोग करना महत्वपूर्ण है।

  1. कर्नल

CUDA में, एक कर्नल जीपीयू पर चलने वाला एक फंक्शन है। यह कई थ्रेड्स द्वारा समानांतर में निष्पादित किया जाता है। यहाँ एक सरल कर्नल का उदाहरण है:

__global__ void vectorAdd(float *a, float *b, float *c, int n)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i &lt; n)
c[i] = a[i] + b[i];
}

यह कर्नल दो वेक्टर्स को तत्व-वार जोड़ता है। __global__ कीवर्ड इंगित करता है कि यह फंक्शन एक CUDA कर्नल है।

CUDA मेमोरी मॉडल

जीपीयू कंप्यूटिंग एप्लिकेशन, लाइब्रेरी, मिडलवेयर और प्रोग्रामिंग भाषाओं का ढेर जो CUDA द्वारा समर्थित है

CUDA मेमोरी मॉडल को समझना कुशल जीपीयू कोड लिखने के लिए महत्वपूर्ण है। CUDA मेमोरी मॉडल होस्ट (सीपीयू) और डिवाइस (जीपीयू) मेमोरी सिस्टम को एकजुट करता है और पूरे मेमोरी हायरार्की को उजागर करता है, जिससे डेवलपर्स को डेटा प्लेसमेंट पर नियंत्रण देने की अनुमति मिलती है।

मेमोरी हायरार्की के लाभ

आधुनिक कंप्यूटिंग सिस्टम, जीपीयू सहित, प्रदर्शन को अनुकूलित करने के लिए मेमोरी हायरार्की का उपयोग करते हैं। यह हायरार्की विभिन्न लेटेंसी, बैंडविड्थ और क्षमता वाले मेमोरी के कई स्तरों से बना है。 स्थानीयता का सिद्धांत यहाँ एक महत्वपूर्ण भूमिका निभाता है:

  1. कालिक स्थानीयता: यदि एक डेटा स्थान संदर्भित किया जाता है, तो यह जल्द ही फिर से संदर्भित किया जाने की संभावना है।
  2. स्थानिक स्थानीयता: यदि एक मेमोरी स्थान संदर्भित किया जाता है, तो आसपास के स्थान भी संदर्भित किए जाने की संभावना है।

इन प्रकार की स्थानीयता को समझने और उपयोग करने से आप CUDA प्रोग्राम्स लिख सकते हैं जो मेमोरी एक्सेस समय को कम करते हैं और थ्रूपुट को अधिकतम करते हैं।

CUDA मेमोरी प्रकारों का विस्तृत विवरण

CUDA का मेमोरी मॉडल विभिन्न प्रकार की मेमोरी को उजागर करता है, प्रत्येक के अपने दायरे, जीवनकाल और प्रदर्शन विशेषताएं हैं:

  1. रजिस्टर: CUDA थ्रेड्स के लिए उपलब्ध सबसे तेज मेमोरी, जो वेरिएबल्स को स्टोर करने के लिए उपयोग की जाती है।
  2. शेयर्ड मेमोरी: ब्लॉक के भीतर थ्रेड्स के बीच साझा की जाने वाली मेमोरी, जो ग्लोबल मेमोरी की तुलना में कम लेटेंसी वाली होती है और थ्रेड्स को सिंक्रोनाइज करने के लिए उपयोगी है।
  3. लोकल मेमोरी: प्रत्येक थ्रेड के लिए विशिष्ट मेमोरी, जो रजिस्टर्स की तुलना में अधिक मात्रा में डेटा स्टोर करने के लिए उपयोग की जाती है।
  4. ग्लोबल मेमोरी: सबसे बड़ा मेमोरी स्पेस, जो सभी थ्रेड्स द्वारा एक्सेस किया जा सकता है। यह उच्च लेटेंसी वाला होता है और आमतौर पर कई थ्रेड्स द्वारा एक्सेस किए जाने वाले डेटा को स्टोर करने के लिए उपयोग किया जाता है।
  5. कॉन्स्टेंट मेमोरी: केवल-पढ़ने वाली मेमोरी जो निरंतर डेटा के लिए उपयोग की जाती है और कैश्ड होती है ताकि कुशलता से एक्सेस की जा सके।
  6. टेक्सचर मेमोरी: विशेष प्रकार की पढ़ने योग्य मेमोरी जो कertain एक्सेस पैटर्न के लिए अनुकूलित होती है, जो ग्राफिक्स एप्लिकेशन में सामान्यतः उपयोग की जाती है।
div]:bg-bg-300 [&_pre]:-mr-4 md:[&_pre]:-mr-9″>

CUDA मशीन लर्निंग के लिए: व्यावहारिक अनुप्रयोग

CUDA C/C++ एप्लिकेशन की संरचना, जहां होस्ट (सीपीयू) कोड डिवाइस (जीपीयू) पर समानांतर कोड के निष्पादन का प्रबंधन करता है।

CUDA C/C++ एप्लिकेशन की संरचना, जहां होस्ट (सीपीयू) कोड डिवाइस (जीपीयू) पर समानांतर कोड के निष्पादन का प्रबंधन करता है।

अब जबकि हमने मूल बातें कवर कर ली हैं, आइए देखें कि CUDA को सामान्य मशीन लर्निंग कार्यों में कैसे लागू किया जा सकता है।

  1. मैट्रिक्स गुणा

मैट्रिक्स गुणा कई मशीन लर्निंग एल्गोरिदम में एक मूलभूत ऑपरेशन है, विशेष रूप से न्यूरल नेटवर्क में। CUDA इस ऑपरेशन को काफी तेज कर सकता है। यहाँ एक सरल कार्यान्वयन है:

__global__ void matrixMulKernel(float *A, float *B, float *C, int N)
{
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
float sum = 0.0f;

<p>if (row &lt; N &amp;&amp; col &lt; N) {
for (int i = 0; i &lt; N; i++) {
sum += A[row * N + i] * B[i * N + col];
}
C[row * N + col] = sum;
}
}</p>

<p>// होस्ट फंक्शन जो कर्नल सेट अप और लॉन्च करता है
void matrixMul(float *A, float *B, float *C, int N)
{
dim3 threadsPerBlock(16, 16);
dim3 numBlocks((N + threadsPerBlock.x - 1) / threadsPerBlock.x,
(N + threadsPerBlock.y - 1) / threadsPerBlock.y);</p>

<p>matrixMulKernel&lt;&gt;(A, B, C, N);
}

यह कार्यान्वयन आउटपुट मैट्रिक्स को ब्लॉक्स में विभाजित करता है, प्रत्येक थ्रेड एक परिणाम तत्व की गणना करता है। जबकि यह बुनियादी संस्करण पहले से ही बड़े मैट्रिक्स के लिए सीपीयू कार्यान्वयन से तेज है, साझा मेमोरी और अन्य तकनीकों का उपयोग करके अभी भी अनुकूलन की गुंजाइश है।

  1. संयोजन ऑपरेशन

कॉन्वोल्यूशनल न्यूरल नेटवर्क (सीएनएन) संयोजन ऑपरेशन पर भारी निर्भर करते हैं। CUDA इन गणनाओं को नाटकीय रूप से तेज कर सकता है। यहाँ एक साधारण 2डी संयोजन कर्नल है:


<p>__global__ void convolution2DKernel(float *input, float *kernel, float *output,
int inputWidth, int inputHeight,
int kernelWidth, int kernelHeight)
{
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;</p>

<p>if (x &lt; inputWidth &amp;&amp; y &lt; inputHeight) {
float sum = 0.0f;
for (int ky = 0; ky &lt; kernelHeight; ky++) {
for (int kx = 0; kx = 0 &amp;&amp; inputX = 0 &amp;&amp; inputY &lt; inputHeight) {
sum += input[inputY * inputWidth + inputX] *
kernel[ky * kernelWidth + kx];
}
}
}
output[y * inputWidth + x] = sum;
}
}</p>

यह कर्नल 2डी संयोजन करता है, प्रत्येक थ्रेड एक आउटपुट पिक्सल की गणना करता है। व्यवहार में, अधिक परिष्कृत कार्यान्वयन साझा मेमोरी का उपयोग करके ग्लोबल मेमोरी एक्सेस को कम करने और विभिन्न कर्नल आकारों के लिए अनुकूलित करने के लिए करेंगे।

  1. स्टोकास्टिक ग्रेडिएंट डिसेंट (एसजीडी)

एसजीडी मशीन लर्निंग में एक मूलभूत अनुकूलन एल्गोरिदम है। CUDA ग्रेडिएंट्स की गणना को कई डेटा बिंदुओं पर समानांतर में कर सकता है। यहाँ एक सरल उदाहरण है रेखीय प्रतिगमन के लिए:


<p>__global__ void sgdKernel(float *X, float *y, float *weights, float learningRate, int n, int d)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i &lt; n) {
float prediction = 0.0f;
for (int j = 0; j &lt; d; j++) {
prediction += X[i * d + j] * weights[j];
}
float error = prediction - y[i];
for (int j = 0; j &lt; d; j++) {
atomicAdd(&amp;weights[j], -learningRate * error * X[i * d + j]);
}
}
}</p>

<p>void sgd(float *X, float *y, float *weights, float learningRate, int n, int d, int iterations)
{
int threadsPerBlock = 256;
int numBlocks = (n + threadsPerBlock - 1) / threadsPerBlock;</p>

<p>for (int iter = 0; iter &lt; iterations; iter++) {
sgdKernel&lt;&gt;(X, y, weights, learningRate, n, d);
}
}</p>

यह कार्यान्वयन वजनों को प्रत्येक डेटा बिंदु के लिए समानांतर में अपडेट करता है। atomicAdd फंक्शन का उपयोग वजनों में समानांतर अपडेट को सुरक्षित रूप से संभालने के लिए किया जाता है।

CUDA को मशीन लर्निंग के लिए अनुकूलित करना

उपरोक्त उदाहरणों ने मशीन लर्निंग कार्यों के लिए CUDA के मूल उपयोग को प्रदर्शित किया है, लेकिन कई अनुकूलन तकनीकें हैं जो प्रदर्शन को और बढ़ा सकती हैं:

  1. संयुक्त मेमोरी एक्सेस

जीपीयू तब अपनी चरम प्रदर्शन प्राप्त करते हैं जब एक वार्प के थ्रेड्स संयुक्त मेमोरी स्थानों तक पहुंचते हैं। सुनिश्चित करें कि आपके डेटा संरचनाएं और एक्सेस पैटर्न संयुक्त मेमोरी एक्सेस को बढ़ावा देते हैं।

  1. साझा मेमोरी का उपयोग

साझा मेमोरी ग्लोबल मेमोरी की तुलना में बहुत तेज है। इसका उपयोग ब्लॉक के भीतर बार-बार एक्सेस किए जाने वाले डेटा को कैश करने के लिए करें।

CUDA के साथ काम करते समय मेमोरी हायरार्की को समझना

CUDA के साथ काम करते समय मेमोरी हायरार्की

यह चित्र एक मल्टी-प्रोसेसर सिस्टम की वास्तुकला को दर्शाता है जिसमें साझा मेमोरी है। प्रत्येक प्रोसेसर के पास अपनी कैश होती है, जो अक्सर उपयोग किए जाने वाले डेटा तक तेजी से पहुंचने की अनुमति देती है। प्रोसेसर एक साझा बस के माध्यम से संवाद करते हैं, जो उन्हें एक बड़े साझा मेमोरी स्पेस से जोड़ती है।

उदाहरण के लिए, मैट्रिक्स गुणा में:


<p>__global__ void matrixMulSharedKernel(float *A, float *B, float *C, int N)
{
__shared__ float sharedA[TILE_SIZE][TILE_SIZE];
__shared__ float sharedB[TILE_SIZE][TILE_SIZE];</p>

<p>int bx = blockIdx.x; int by = blockIdx.y;
int tx = threadIdx.x; int ty = threadIdx.y;</p>

<p>int row = by * TILE_SIZE + ty;
int col = bx * TILE_SIZE + tx;</p>

float sum = 0.0f;

<p>for (int tile = 0; tile &lt; (N + TILE_SIZE - 1) / TILE_SIZE; tile++) {
if (row &lt; N &amp;&amp; tile * TILE_SIZE + tx &lt; N)
sharedA[ty][tx] = A[row * N + tile * TILE_SIZE + tx];
else
sharedA[ty][tx] = 0.0f;</p>

<p>if (col &lt; N &amp;&amp; tile * TILE_SIZE + ty &lt; N)
sharedB[ty][tx] = B[(tile * TILE_SIZE + ty) * N + col];
else
sharedB[ty][tx] = 0.0f;</p>

__syncthreads();

<p>for (int k = 0; k &lt; TILE_SIZE; k++)
sum += sharedA[ty][k] * sharedB[k][tx];</p>

__syncthreads();
}

<p>if (row &lt; N &amp;&amp; col &lt; N)
C[row * N + col] = sum;
}</p>

यह अनुकूलित संस्करण साझा मेमोरी का उपयोग करके ग्लोबल मेमोरी एक्सेस को कम करता है, जिससे बड़े मैट्रिक्स के लिए काफी प्रदर्शन में सुधार होता है।

  1. असिंक्रोनस ऑपरेशन

CUDA असिंक्रोनस ऑपरेशन को समर्थन करता है, जिससे आप गणना को डेटा ट्रांसफर के साथ ओवरलैप कर सकते हैं। यह मशीन लर्निंग पाइपलाइन में विशेष रूप से उपयोगी है जहां आप अगले बैच के डेटा की तैयारी कर सकते हैं जबकि वर्तमान बैच प्रोसेस किया जा रहा है।

cudaStream_t stream1, stream2;
cudaStreamCreate(&amp;stream1);
cudaStreamCreate(&amp;stream2);

<p>// असिंक्रोनस मेमोरी ट्रांसफर और कर्नल लॉन्च
cudaMemcpyAsync(d_data1, h_data1, size, cudaMemcpyHostToDevice, stream1);
myKernel&lt;&gt;(d_data1, ...);</p>

<p>cudaMemcpyAsync(d_data2, h_data2, size, cudaMemcpyHostToDevice, stream2);
myKernel&lt;&gt;(d_data2, ...);</p>

<p>cudaStreamSynchronize(stream1);
cudaStreamSynchronize(stream2);
  1. टेंसर कोर

मशीन लर्निंग वर्कलोड के लिए, एनवीडिया के टेंसर कोर (नए जीपीयू आर्किटेक्चर में उपलब्ध) मैट्रिक्स गुणा और संयोजन ऑपरेशन के लिए महत्वपूर्ण गति प्रदान कर सकते हैं। cuDNN और cuBLAS जैसे लाइब्रेरी स्वचालित रूप से टेंसर कोर का लाभ उठाती हैं जब उपलब्ध होते हैं।

चुनौतियां और विचार

CUDA मशीन लर्निंग के लिए कई लाभ प्रदान करता है, लेकिन कुछ संभावित चुनौतियों के बारे में जागरूक रहना महत्वपूर्ण है:

  1. मेमोरी प्रबंधन: जीपीयू मेमोरी सिस्टम मेमोरी की तुलना में सीमित है। कुशल मेमोरी प्रबंधन विशेष रूप से बड़े डेटासेट या मॉडल के साथ काम करते समय महत्वपूर्ण है।
  2. डेटा ट्रांसफर ओवरहेड: सीपीयू और जीपीयू के बीच डेटा ट्रांसफर एक बोतलनेक हो सकता है। ट्रांसफर को कम से कम करें और जहां संभव हो असिंक्रोनस ऑपरेशन का उपयोग करें।
  3. सटीकता: जीपीयू आमतौर पर एकल सटीकता (एफपी32) गणनाओं में उत्कृष्ट होते हैं। जबकि दोहरी सटीकता (एफपी64) के लिए समर्थन में सुधार हुआ है, यह अक्सर धीमा होता है। कई मशीन लर्निंग कार्य कम सटीकता (जैसे, एफपी16) के साथ अच्छा प्रदर्शन कर सकते हैं, जिसे आधुनिक जीपीयू बहुत कुशलता से संभालते हैं।
  4. कोड जटिलता: कुशल CUDA कोड लिखना सीपीयू कोड की तुलना में अधिक जटिल हो सकता है। cuDNN, cuBLAS, और TensorFlow या PyTorch जैसे फ्रेमवर्क का लाभ उठाकर कुछ जटिलता को समाहित किया जा सकता है।

एकाधिक जीपीयू पर जाना

जैसे-जैसे मशीन लर्निंग मॉडल का आकार बढ़ता है और जटिलता बढ़ती है, एक जीपीयू अकेले कार्यभार को संभालने के लिए पर्याप्त नहीं हो सकता है। CUDA आपको अपने अनुप्रयोग को एकाधिक जीपीयू में स्केल करने की अनुमति देता है, चाहे वह एक ही नोड में हो या क्लस्टर में।

एकाधिक जीपीयू का उपयोग करने के कारण

  1. समस्या डोमेन का आकार: आपका डेटासेट या मॉडल एक ही जीपीयू की मेमोरी में फिट नहीं हो सकता है।
  2. थ्रूपुट और दक्षता: यहां तक कि अगर एक कार्य एक ही जीपीयू में फिट होता है, तो एकाधिक जीपीयू का उपयोग करके आप एक ही समय में कई कार्यों को संसाधित करके थ्रूपुट बढ़ा सकते हैं।

CUDA प्रोग्रामिंग संरचना

CUDA का प्रभावी ढंग से उपयोग करने के लिए, इसकी प्रोग्रामिंग संरचना को समझना आवश्यक है, जिसमें कर्नल (जीपीयू पर चलने वाले फंक्शन) लिखना और होस्ट (सीपीयू) और डिवाइस (जीपीयू) के बीच मेमोरी प्रबंधन शामिल है।

होस्ट बनाम डिवाइस मेमोरी

CUDA में, मेमोरी होस्ट और डिवाइस के लिए अलग से प्रबंधित की जाती है। निम्नलिखित प्राथमिक फंक्शन मेमोरी प्रबंधन के लिए उपयोग किए जाते हैं:

  • cudaMalloc: डिवाइस पर मेमोरी आवंटित करता है।
  • cudaMemcpy: होस्ट और डिवाइस के बीच डेटा की प्रतिलिपि बनाता है।
  • cudaFree: डिवाइस पर मेमोरी मुक्त करता है।

उदाहरण: दो सरणियों को जोड़ना

आइए एक उदाहरण देखें जो दो सरणियों को जोड़ता है:


<p>__global__ void sumArraysOnGPU(float *A, float *B, float *C, int N) {
int idx = threadIdx.x + blockIdx.x * blockDim.x;
if (idx &lt; N) C[idx] = A[idx] + B[idx];
}</p>

<p>int main() {
int N = 1024;
size_t bytes = N * sizeof(float);</p>

<p>float *h_A, *h_B, *h_C;
h_A = (float*)malloc(bytes);
h_B = (float*)malloc(bytes);
h_C = (float*)malloc(bytes);</p>

<p>float *d_A, *d_B, *d_C;
cudaMalloc(&amp;d_A, bytes);
cudaMalloc(&amp;d_B, bytes);
cudaMalloc(&amp;d_C, bytes);</p>

<p>cudaMemcpy(d_A, h_A, bytes, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, bytes, cudaMemcpyHostToDevice);</p>

<p>int blockSize = 256;
int gridSize = (N + blockSize - 1) / blockSize;</p>

<p>sumArraysOnGPU&lt;&gt;(d_A, d_B, d_C, N);</p>

<p>cudaMemcpy(h_C, d_C, bytes, cudaMemcpyDeviceToHost);</p>

<p>cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);</p>

free(h_A);
free(h_B);
free(h_C);

return 0;
}

इस उदाहरण में, मेमोरी होस्ट और डिवाइस दोनों पर आवंटित की जाती है, डेटा होस्ट से डिवाइस पर कॉपी किया जाता है, और फिर कर्नल लॉन्च किया जाता है ताकि गणना की जा सके।

निष्कर्ष

CUDA मशीन लर्निंग इंजीनियरों के लिए एक शक्तिशाली उपकरण है जो अपने मॉडल को तेज करना और बड़े डेटासेट को संभालना चाहते हैं। CUDA मेमोरी मॉडल को समझने, मेमोरी एक्सेस को अनुकूलित करने, और एकाधिक जीपीयू का लाभ उठाकर, आप अपने मशीन लर्निंग अनुप्रयोगों के प्रदर्शन को काफी बढ़ा सकते हैं।

जबकि हमने इस लेख में मूल बातें और कुछ उन्नत विषयों को कवर किया है, CUDA एक विशाल क्षेत्र है जिसमें निरंतर विकास हो रहा है। नवीनतम CUDA रिलीज़, जीपीयू आर्किटेक्चर, और मशीन लर्निंग लाइब्रेरी के साथ अद्यतित रहें ताकि आप इस शक्तिशाली प्रौद्योगिकी का सर्वोत्तम उपयोग कर सकें।

मैं पिछले पांच वर्षों से मशीन लर्निंग और डीप लर्निंग की दुनिया में खुद को डूबो रहा हूं। मेरा जुनून और विशेषज्ञता ने मुझे 50 से अधिक विविध सॉफ्टवेयर इंजीनियरिंग परियोजनाओं में योगदान देने के लिए प्रेरित किया है, जिनमें से अधिकांश में एआई/एमएल पर विशेष ध्यान केंद्रित किया गया है। मेरी जारी जिज्ञासा ने मुझे प्राकृतिक भाषा प्रसंस्करण की ओर आकर्षित किया है, जिस क्षेत्र को मैं आगे अन्वेषण करने के लिए उत्सुक हूं।