2013-04-17 29 views
5

Làm cách nào để tách mã hạt nhân cuda và các mã cpp khác trong dự án? Tôi muốn thu thập tất cả các định nghĩa hạt nhân bên trong một tệp duy nhất như các tệp cpp khác gọi chúng trong thời gian cần thiết. Tôi cố gắng viết tất cả các hạt nhân bên trong kernel.cu và gọi các hạt nhân bằng cách bao gồm tệp kernel.cu nhưng nó đưa ra lỗi sau khi biên dịch.cách giữ mã hạt nhân bên trong tệp .cu riêng biệt ngoài tệp .cpp chính?

/usr/bin/ld: error: ./vector_summation.o: multiple definition of 

'perform_summation_method1(int*, int)' 
/usr/bin/ld: ./kernels.o: previous definition here 
/usr/bin/ld: error: ./vector_summation.o: multiple definition of '__device_stub__Z25perform_summation_method1Pii(int*, int)' 
/usr/bin/ld: ./kernels.o: previous definition here 
/usr/bin/ld: error: ./vector_summation.o: multiple definition of '__device_stub__Z25perform_summation_method2PiS_i(int*, int*, int)' 
/usr/bin/ld: ./kernels.o: previous definition here 
/usr/bin/ld: error: ./vector_summation.o: multiple definition of 'perform_summation_method2(int*, int*, int)' 
/usr/bin/ld: ./kernels.o: previous definition here 
/usr/bin/ld: error: ./vector_summation.o: multiple definition of '__device_stub__Z25perform_summation_method3PiS_i(int*, int*, int)' 
/usr/bin/ld: ./kernels.o: previous definition here 
/usr/bin/ld: error: ./vector_summation.o: multiple definition of 'perform_summation_method3(int*, int*, int)' 
/usr/bin/ld: ./kernels.o: previous definition here 

Trả lời

13

Bạn thực chất giống như cách bạn làm với các tệp/mô-đun cpp thông thường. Trong C++, bạn thường không bao gồm một tệp .cpp trong tệp khác, khi bạn muốn truy cập các hàm từ tệp khác. Bạn bao gồm tiêu đề thường chỉ chứa các nguyên mẫu chức năng.

Dưới đây là một ví dụ:

test.h:

void my_cuda_func(); 

main.cpp:

#include <stdio.h> 
#include "test.h" 

int main(){ 
    my_cuda_func(); 
    return 0; 
} 

test.cu:

#include <stdio.h> 
#include "test.h" 


__global__ void my_kernel(){ 
    printf("Hello!\n"); 
} 

void my_cuda_func(){ 
    my_kernel<<<1,1>>>(); 
    cudaDeviceSynchronize(); 
} 

sử dụng các lệnh sau để xây dựng:

g++ -c main.cpp 
nvcc -arch=sm_20 -c test.cu 
g++ -L/usr/local/cuda/lib64 -lcudart -o test main.o test.o 

Có các cách tiếp cận khác tất nhiên. Nếu bạn muốn liên kết tới C thay vì C++, bạn cần tính đến điều đó. Nếu bạn muốn gọi hạt nhân trực tiếp từ các mô-đun khác thay vì sử dụng một hàm bao bọc, thì bạn cần phải chuyển tất cả các mô-đun của bạn thông qua nvcc thay vì g ++ (và tất cả chúng phải là tệp .cu). Ngoài ra, nếu bạn muốn có nhiều tệp với mã thiết bị GPU (ví dụ: định nghĩa hạt nhân) thì bạn cần làm quen với việc sử dụng device code linker.

Để hoàn chỉnh, đây là ví dụ trên lại làm việc để hiển thị những gì bạn cần làm nếu muốn tất cả các định nghĩa hạt nhân trong một tập tin, nhưng có thể gọi hạt nhân trực tiếp từ mô-đun khác:

test.h:

__global__ void my_kernel(); 

main.cu:

#include <stdio.h> 
#include "test.h" 

int main(){ 
    my_kernel<<<1,1>>>(); 
    cudaDeviceSynchronize(); 
    return 0; 
} 

test.cu:

#include <stdio.h> 
#include "test.h" 


__global__ void my_kernel(){ 
    printf("Hello!\n"); 
} 

xây dựng với:

nvcc -arch=sm_20 -c main.cu 
nvcc -arch=sm_20 -c test.cu 
nvcc -arch=sm_20 -o test main.o test.o 
1

Bạn có thể tạo tiêu đề CUDA tập tin *.cuh và bao gồm nó như là một tiêu đề tiêu chuẩn. Tôi sẽ không chỉ đặt các hạt nhân trong một tệp riêng biệt, thay vì đặt chúng cùng với một số hàm khởi tạo và chỉ đặt các hàm này vào tiêu đề, vì bạn thường không gọi các hạt nhân từ mã bên ngoài, bạn gọi một số hàm sẽ xử lý bộ nhớ vv tôi thường làm cho tiêu đề như thế này:

#ifndef __CUDAHEADER_CUH__ 
#define __CUDAHEADER_CUH__ 

/** Initialize cuda stuff */ 
void cudaInit(Data * host_data); 

/** Cleanup, frees resources used by the device. */ 
void cudaFinalize(); 

#endif 

và sau đó là tập tin với hạt nhân, phương pháp thiết bị và các phương pháp này có thể xử lý CUDA thứ:

#include "cudaHeader.cuh" 

//some global variables like: 
Data * device_data; 

//some kernels and device functions: 
__global__ void someKernel(data * device_data) { 
    ... 
} 

void cudaInit(Data * host_data) { 
    some cudaMalloc() 
    some cudaMemcpy() 
    someKernel<<< gridRes, blockRes >>>(device_data); 
} 


void cudaFinalize() { 
    cudaFree(device_data); 
} 

Nhưng có nhiều cách làm thế nào để xử lý ma cua ban...

-1

dụ đầu tiên: Tôi nghĩ rằng bạn phải xây dựng (dòng cuối cùng) như thế này:

g++ -L/usr/local/cuda/lib64 -o test main.o test.o -lcudart 

ví dụ: đặt thư viện cuối cùng trong liên kết. (Tôi cũng cần)

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