2011-02-16 109 views
7

Tôi bị ấn tượng với phép nhân Ma trận trên CUDA. Ma trận sản phẩm thu được luôn bằng không. Tôi đã đọc một số mã mẫu như matrix multiplication in cuda để giải quyết vấn đề của tôi, nhưng tất cả đều vô ích.Phép nhân ma trận sử dụng CUDA

Ngoài kết quả thất thường là 0, kích thước tối đa của "Chiều rộng" (mã bên dưới) không phải là 512. Tôi không thể gỡ lỗi vị trí của sự cố. Có thể chúng ta có thể thảo luận về StackOverflow.

tôi đề cập "Lập trình xử lý Massively Parallel"

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

int main(void) { 
    void MatrixMultiplication(float *, float *, float *, int); 
    const int Width = 5; 
    float M[Width*Width], N[Width*Width], P[Width*Width]; 
    for(int i = 0; i < (Width*Width) ; i++) { 
     M[i] = 5; 
     N[i] = 5; 
     P[i] = 0; 
    } 
    MatrixMultiplication(M, N, P, Width); 
    for(int i = 0; i < (Width*Width) ; i++) { 
     printf("%d \n", P[i]); 
    } 
    int quit; 
    scanf("%d",&quit); 
    return 0; 
} 

//Matrix multiplication kernel - thread specification 
__global__ void MatrixMulKernel(float *Md, float *Nd, float *Pd, int Width) { 
    //2D Thread ID 
    int tx = threadIdx.x; 
    int ty = threadIdx.y; 

    //Pvalue stores the Pd element that is computed by the thread 
    float Pvalue = 0; 

    for(int k = 0; k < Width ; ++k) { 
     float Mdelement = Md[ty*Width + k]; 
     float Ndelement = Nd[k*Width + tx]; 
     Pvalue += (Mdelement*Ndelement); 
    } 

    Pd[ty*Width + tx] = Pvalue; 
} 

void MatrixMultiplication(float *M, float *N, float *P, int Width) { 
    int size = Width*Width*sizeof(float); 
    float *Md, *Nd, *Pd; 

    //Transfer M and N to device memory 
    cudaMalloc((void**)&Md, size); 
    cudaMemcpy(Md,M,size,cudaMemcpyHostToDevice); 
    cudaMalloc((void**)&Nd, size); 
    cudaMemcpy(Nd,N,size,cudaMemcpyHostToDevice); 

    //Allocate P on the device 
    cudaMalloc((void**)&Pd,size); 

    //Setup the execution configuration 
    dim3 dimBlock(Width,Width); 
    dim3 dimGrid(1,1); 

    //Launch the device computation threads! 
    MatrixMulKernel<<<dimGrid,dimBlock>>>(Md,Nd,Pd,Width); 

    //Transfer P from device to host 
    cudaMemcpy(P,Pd,size,cudaMemcpyDeviceToHost); 

    //Free device matrices 
    cudaFree(Md); 
    cudaFree(Nd); 
    cudaFree(Pd); 
} 
+2

Để có được định dạng mã phù hợp, bạn cần thụt lề tất cả mã với 4 dấu cách. Bạn có thể làm điều này dễ dàng bằng cách làm nổi bật mã của bạn và nhấn 'Ctrl + K'. –

+0

Cảm ơn Jeff! Chỉ cần thực hiện điều đó –

+0

Nếu bạn không cần phải gắn mã của riêng mình, Hướng dẫn lập trình CUDA C có khả năng thực thi ma trận tuyệt vời có thể xử lý ma trận với các kích thước khác so với sức mạnh của hai và được tối ưu hóa bằng bộ nhớ dùng chung. Rất khuyên bạn nên sử dụng nó cho thế giới thực và học tập. –

Trả lời

1

tôi đã tìm ra những gì đã sai rồi. Hãy phân tích nó:

điểm 1: Các nhiệm vụ để loại bỏ các bao giờ đơn điệu "giá trị zero"

Như đã đề cập, bạn phải thay thế printf("%d \n", P[i]); như printf("%f \n", P[i]);

điểm 2: Tại sao chương trình không thành công với giá trị là Chiều rộng 512?

Thực ra nó sẽ không thành công ngay cả một giá trị nhỏ như 23. Tại sao? Vì 23 * 23 là> 512 (Số lượng chủ đề tối đa mà GPU có thể có cho mỗi khối kể từ hôm nay!)

0

Trong MatrixMulKernel của bạn hoạt động của mình cho vòng lặp là như

for(int k = 0; k < Width ; ++k) 
{ 
    //rest of code  
} 

Thay vì Width, bạn phải sử dụng Width*Width như mảng của bạn có kích thước Width*Width.

+1

Toàn bộ điểm của việc sử dụng song song CUDA là để loại bỏ chi phí tính toán. Trong trường hợp này, mỗi luồng chỉ chịu trách nhiệm cho 1 kết quả của ma trận sản phẩm. Một kết quả (phần tử) của ma trận sản phẩm có thể được tìm thấy bằng cách sử dụng các phép lặp "Chiều rộng". Vì vậy, chiều rộng * Chiều rộng sẽ không hoạt động trong mọi trường hợp. –

+0

như @Gaurav đã nói, Chiều rộng * Chiều rộng sẽ chỉ thổi bộ nhớ lên .. – ardiyu07

4

Bạn đang làm tốt đến thời điểm này:

for(int i = 0; i < (Width*Width) ; i++) { 
    printf("%d \n", P[i]); 
} 

tôi đã thay đổi nó để% f (vì đó là một float) và tất cả đều in độc đáo :)

$ ./test.exe 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
+0

Thật vậy! Mặc dù tôi đã tìm ra nó mà không cần đọc câu trả lời của bạn và chỉ muốn đăng nó. –

Các vấn đề liên quan