2011-05-26 14 views
9

मैं cuda के लिए नया हूँ। मैं एक दो सरणी में दो 2 डी सरणी जोड़ना चाहता हूँ। मैं निम्नलिखित कोड का उपयोग करें:मैं लूप के लिए नेस्टेड का उपयोग करके दो 2 डी (पेंट) सरणी कैसे जोड़ सकता हूं?

cudaMallocPitch((void**)&device_a, &pitch, 2*sizeof(int),2); 
cudaMallocPitch((void**)&device_b, &pitch, 2*sizeof(int),2); 
cudaMallocPitch((void**)&device_c, &pitch, 2*sizeof(int),2); 

अब मेरी समस्या मुझे नहीं है कि के रूप में 2-डी सरणी सभी चपटा मेरी कर्नेल कोड मैं di करना चाहते हैं में इन सरणी का उपयोग करना चाहते पाश & के लिए दो का उपयोग कर रहा है परिणाम को है तीसरी सरणी में

__global__ void add(int *dev_a ,int *dev_b,int* dec_c) 
{ 
    for i=0;i<2;i++) 
    { 
     for j=0;j<2;j++) 
     { 
     dev_c[i][j]=dev_a[i][j]+dev_b[i][j]; 
     } 
    } 
} 

मैं इसे CUDA में कैसे कर सकता हूं? कृपया मुझे बताएं कि इस तरह से 2-डी सरणी का उपयोग कैसे करें?

2 डी-सरणी का उपयोग करने के लिए कर्नेल कॉल क्या होना चाहिए? यदि संभव हो, तो कृपया कोड नमूने का उपयोग करके समझाएं।

+1

कृपया कोड - इंडेंट को 4 रिक्त स्थान से प्रारूपित करें। – sje397

उत्तर

16

संक्षिप्त उत्तर है, आप नहीं कर सकते हैं। cudaMallocPitch() फ़ंक्शन वास्तव में इसका नाम बताता है, यह पिक्चर रैखिक मेमोरी आवंटित करता है, जहां पिच को GPU मेमोरी कंट्रोलर और बनावट हार्डवेयर के लिए इष्टतम होने के लिए चुना जाता है।

हैं आप कर्नेल में संकेत के एरे उपयोग करना चाहता था, कर्नेल कोड इस तरह देखना होगा:

__global___ void add(int *dev_a[] ,int *dev_b[], int* dec_c[]) 
{ 
    for i=0;i<2;i++) { 
     for j=0;j<2;j++) { 
     dev_c[i][j]=dev_a[i][j]+dev_b[i][j]; 
     } 
    } 
} 

और फिर आप मेजबान पक्ष पर नेस्ट cudaMalloc कॉल की जरूरत है निर्माण करने के लिए होगा पॉइंटर्स की सरणी और इसे डिवाइस मेमोरी में कॉपी करें। अपने नहीं बल्कि तुच्छ 2x2 उदाहरण के लिए, कोड आवंटित करने के लिए एक सारिणी इस प्रकार दिखाई देगा:

int ** h_a = (int **)malloc(2 * sizeof(int *)); 
cudaMalloc((void**)&h_a[0], 2*sizeof(int)); 
cudaMalloc((void**)&h_a[1], 2*sizeof(int)); 

int **d_a; 
cudaMalloc((void ***)&d_a, 2 * sizeof(int *)); 
cudaMemcpy(d_a, h_a, 2*sizeof(int *), cudaMemcpyHostToDevice); 

कौन सा d_a में संकेत के आवंटित डिवाइस सरणी छोड़ना होगा, और आप अपने कर्नेल में है कि पास चला जाएगा।

कोड जटिलता और प्रदर्शन कारणों के लिए, आप वास्तव में ऐसा नहीं करना चाहते हैं, सीयूडीए कोड में पॉइंटर्स के सरणी का उपयोग करके कठोर और रैखिक स्मृति का उपयोग करके वैकल्पिक से धीमा है।

#include <cstdio> 
__global__ void add(int * dev_a[], int * dev_b[], int * dev_c[]) 
{ 
    for(int i=0;i<2;i++) 
    { 
     for(int j=0;j<2;j++) 
     { 
      dev_c[i][j]=dev_a[i][j]+dev_b[i][j]; 
     } 
    } 
} 

inline void GPUassert(cudaError_t code, char * file, int line, bool Abort=true) 
{ 
    if (code != 0) { 
     fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),file,line); 
     if (Abort) exit(code); 
    }  
} 

#define GPUerrchk(ans) { GPUassert((ans), __FILE__, __LINE__); } 

int main(void) 
{ 
    const int aa[2][2]={{1,2},{3,4}}; 
    const int bb[2][2]={{5,6},{7,8}}; 
    int cc[2][2]; 

    int ** h_a = (int **)malloc(2 * sizeof(int *)); 
    for(int i=0; i<2;i++){ 
     GPUerrchk(cudaMalloc((void**)&h_a[i], 2*sizeof(int))); 
     GPUerrchk(cudaMemcpy(h_a[i], &aa[i][0], 2*sizeof(int), cudaMemcpyHostToDevice)); 
    } 

    int **d_a; 
    GPUerrchk(cudaMalloc((void ***)&d_a, 2 * sizeof(int *))); 
    GPUerrchk(cudaMemcpy(d_a, h_a, 2*sizeof(int *), cudaMemcpyHostToDevice)); 

    int ** h_b = (int **)malloc(2 * sizeof(int *)); 
    for(int i=0; i<2;i++){ 
     GPUerrchk(cudaMalloc((void**)&h_b[i], 2*sizeof(int))); 
     GPUerrchk(cudaMemcpy(h_b[i], &bb[i][0], 2*sizeof(int), cudaMemcpyHostToDevice)); 
    } 

    int ** d_b; 
    GPUerrchk(cudaMalloc((void ***)&d_b, 2 * sizeof(int *))); 
    GPUerrchk(cudaMemcpy(d_b, h_b, 2*sizeof(int *), cudaMemcpyHostToDevice)); 

    int ** h_c = (int **)malloc(2 * sizeof(int *)); 
    for(int i=0; i<2;i++){ 
     GPUerrchk(cudaMalloc((void**)&h_c[i], 2*sizeof(int))); 
    } 

    int ** d_c; 
    GPUerrchk(cudaMalloc((void ***)&d_c, 2 * sizeof(int *))); 
    GPUerrchk(cudaMemcpy(d_c, h_c, 2*sizeof(int *), cudaMemcpyHostToDevice)); 

    add<<<1,1>>>(d_a,d_b,d_c); 
    GPUerrchk(cudaPeekAtLastError()); 

    for(int i=0; i<2;i++){ 
     GPUerrchk(cudaMemcpy(&cc[i][0], h_c[i], 2*sizeof(int), cudaMemcpyDeviceToHost)); 
    } 

    for(int i=0;i<2;i++) { 
     for(int j=0;j<2;j++) { 
      printf("(%d,%d):%d\n",i,j,cc[i][j]); 
     } 
    } 

    return cudaThreadExit(); 
} 

मैं सुझाव है कि आप आप जब तक यह अध्ययन:


दिखाने के लिए क्या मूर्खता संकेत के एरे उपयोग कर रहा है CUDA में, यहाँ अपने नमूना समस्या का एक पूरा काम कर उदाहरण जो ऊपर दो विचारों को जोड़ती है समझें कि यह क्या करता है, और रैखिक स्मृति का उपयोग करने की तुलना में यह इतना खराब विचार क्यों है।

+0

हाँ आप सही हैं। अब मान लीजिए कि मैं यह करता हूं कि मेरा कर्नेल कॉल – user513164

+0

धन्यवाद। हाँ, आप सही हैं। मान लीजिए कि मैं ऐसा करता हूं कि मेरा कर्नेल कॉल क्या होना चाहिए? एक बात मैं कहूंगा कि मैं cudaMalloc ((शून्य ***) और d_a, 2 का उपयोग करता हूं * आकार (int *)); लेकिन यह त्रुटि दिखाता है; h_a के लिए एक और बात आप cuda malloc का उपयोग क्यों कर रहे हैं कृपया – user513164

2

आपको डिवाइस के अंदर loops के लिए उपयोग करने की आवश्यकता नहीं है। इस कोड को आज़माएं।

#include <stdio.h> 
#include <cuda.h> 
#include <stdlib.h> 
#include <time.h> 

#define N 800 
__global__ void matrixAdd(float* A, float* B, float* C){ 

int i = threadIdx.x; 
int j = blockIdx.x; 
C[N*j+i] = A[N*j+i] + B[N*j+i]; 
} 

int main (void) { 
clock_t start = clock(); 
float a[N][N], b[N][N], c[N][N]; 
float *dev_a, *dev_b, *dev_c; 

cudaMalloc((void **)&dev_a, N * N * sizeof(float)); 
cudaMalloc((void **)&dev_b, N * N * sizeof(float)); 
cudaMalloc((void **)&dev_c, N * N * sizeof(float)); 

for (int i = 0; i < N; i++){ 
    for (int j = 0; j < N; j++){  
     a[i][j] = rand() % 10; 
     b[i][j] = rand() % 10; 
    } 
} 

cudaMemcpy(dev_a, a, N * N * sizeof(float), cudaMemcpyHostToDevice); 
cudaMemcpy(dev_b, b, N * N * sizeof(float), cudaMemcpyHostToDevice); 

matrixAdd <<<N,N>>> (dev_a, dev_b, dev_c); 
cudaMemcpy(c, dev_c, N * N * sizeof(float), cudaMemcpyDeviceToHost); 

for (int i = 0; i < N; i++){ 
    for (int j = 0; j < N; j++){ 
    printf("[%d, %d ]= %f + %f = %f\n",i,j, a[i][j], b[i][j], c[i][j]); 
    } 
} 
printf("Time elapsed: %f\n", ((double)clock() - start)/CLOCKS_PER_SEC); 

cudaFree(dev_a); 
cudaFree(dev_b); 
cudaFree(dev_c); 

return 0; 
} 
+1

समझाएं यह स्थिर आवंटित सरणी के लिए काम करता है जहां आयाम संकलन समय पर ज्ञात हैं। किसी भी प्रकार के गतिशील आवंटन (उदा। 'CudaMalloc', आदि) के लिए जैसे प्रश्न में संकेत दिया गया है, यह काम नहीं करेगा। –

+0

जिस तरह से आप कर्नेल को पास करने से पहले सरणी को अभी भी फ़्लैट कर रहे हैं, जो प्रश्न में उपयोगकर्ता नहीं चाहता है। – MuneshSingh

संबंधित मुद्दे