Dưới đây là một ví dụ linux chia sẻ sự sáng tạo đối tượng dọc theo dòng bạn đã chỉ định:
- tạo một thư viện chia sẻ chứa hạt nhân CUDA của tôi có tiêu đề/tiêu đề CUDA miễn phí .
- tạo tệp thi hành thử nghiệm cho thư viện được chia sẻ.
Đầu tiên là thư viện được chia sẻ. Các lệnh xây dựng cho điều này là như sau:
nvcc -arch=sm_20 -Xcompiler '-fPIC' -dc test1.cu test2.cu
nvcc -arch=sm_20 -Xcompiler '-fPIC' -dlink test1.o test2.o -o link.o
g++ -shared -o test.so test1.o test2.o link.o -L/usr/local/cuda/lib64 -lcudart
Có vẻ như bạn có thể bị thiếu bước thứ hai nêu trên trong makefile của bạn, nhưng tôi đã không phân tích nếu có bất kỳ vấn đề khác với makefile của bạn.
Bây giờ, đối với các bài kiểm tra thực thi, các lệnh xây dựng như sau:
g++ -c main.cpp
g++ -o testmain main.o test.so
Để chạy nó, bạn chỉ cần thực hiện testmain
thực thi, nhưng hãy chắc chắn thư viện test.so
là trên LD_LIBRARY_PATH
của bạn.
Đây là những tập tin tôi sử dụng cho mục đích thử nghiệm:
test1.h:
int my_test_func1();
test1.cu:
#include <stdio.h>
#include "test1.h"
#define DSIZE 1024
#define DVAL 10
#define nTPB 256
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
__global__ void my_kernel1(int *data){
int idx = threadIdx.x + (blockDim.x *blockIdx.x);
if (idx < DSIZE) data[idx] =+ DVAL;
}
int my_test_func1(){
int *d_data, *h_data;
h_data = (int *) malloc(DSIZE * sizeof(int));
if (h_data == 0) {printf("malloc fail\n"); exit(1);}
cudaMalloc((void **)&d_data, DSIZE * sizeof(int));
cudaCheckErrors("cudaMalloc fail");
for (int i = 0; i < DSIZE; i++) h_data[i] = 0;
cudaMemcpy(d_data, h_data, DSIZE * sizeof(int), cudaMemcpyHostToDevice);
cudaCheckErrors("cudaMemcpy fail");
my_kernel1<<<((DSIZE+nTPB-1)/nTPB), nTPB>>>(d_data);
cudaDeviceSynchronize();
cudaCheckErrors("kernel");
cudaMemcpy(h_data, d_data, DSIZE * sizeof(int), cudaMemcpyDeviceToHost);
cudaCheckErrors("cudaMemcpy 2");
for (int i = 0; i < DSIZE; i++)
if (h_data[i] != DVAL) {printf("Results check failed at offset %d, data was: %d, should be %d\n", i, h_data[i], DVAL); exit(1);}
printf("Results check 1 passed!\n");
return 0;
}
test2.h:
int my_test_func2();
test2.cu:
#include <stdio.h>
#include "test2.h"
#define DSIZE 1024
#define DVAL 20
#define nTPB 256
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
__global__ void my_kernel2(int *data){
int idx = threadIdx.x + (blockDim.x *blockIdx.x);
if (idx < DSIZE) data[idx] =+ DVAL;
}
int my_test_func2(){
int *d_data, *h_data;
h_data = (int *) malloc(DSIZE * sizeof(int));
if (h_data == 0) {printf("malloc fail\n"); exit(1);}
cudaMalloc((void **)&d_data, DSIZE * sizeof(int));
cudaCheckErrors("cudaMalloc fail");
for (int i = 0; i < DSIZE; i++) h_data[i] = 0;
cudaMemcpy(d_data, h_data, DSIZE * sizeof(int), cudaMemcpyHostToDevice);
cudaCheckErrors("cudaMemcpy fail");
my_kernel2<<<((DSIZE+nTPB-1)/nTPB), nTPB>>>(d_data);
cudaDeviceSynchronize();
cudaCheckErrors("kernel");
cudaMemcpy(h_data, d_data, DSIZE * sizeof(int), cudaMemcpyDeviceToHost);
cudaCheckErrors("cudaMemcpy 2");
for (int i = 0; i < DSIZE; i++)
if (h_data[i] != DVAL) {printf("Results check failed at offset %d, data was: %d, should be %d\n", i, h_data[i], DVAL); exit(1);}
printf("Results check 2 passed!\n");
return 0;
}
main.cpp:
#include <stdio.h>
#include "test1.h"
#include "test2.h"
int main(){
my_test_func1();
my_test_func2();
return 0;
}
Khi tôi biên soạn theo các lệnh được đưa ra, và chạy ./testmain
tôi nhận được:
$ ./testmain
Results check 1 passed!
Results check 2 passed!
Lưu ý rằng nếu bạn thích, bạn có thể tạo ra một libtest.so
thay vì test.so
và sau đó bạn có thể sử dụng trình tự xây dựng đã sửa đổi để thực thi thử nghiệm:
g++ -c main.cpp
g++ -o testmain main.o -L. -ltest
Tôi không tin nó tạo ra bất kỳ sự khác biệt nào, nhưng nó có thể là cú pháp quen thuộc hơn.
Tôi chắc chắn có nhiều cách để thực hiện việc này. Đây chỉ là một ví dụ. Bạn cũng có thể xem lại phần có liên quan của nvcc manual và cũng xem lại examples.
EDIT: Tôi đã thử nghiệm điều này dưới cuda 5.5 RC và bước liên kết ứng dụng cuối cùng đã phàn nàn về việc không tìm thấy lib cudart (warning: libcudart.so.5.5., needed by ./libtest.so, not found
). Tuy nhiên sửa đổi tương đối đơn giản sau đây (ví dụ Makefile) nên làm việc theo hoặc cuda 5.0 hoặc cuda 5.5.
Makefile:
testmain : main.cpp libtest.so
g++ -c main.cpp
g++ -o testmain -L. -ldl -Wl,-rpath,. -ltest -L/usr/local/cuda/lib64 -lcudart main.o
libtest.so : link.o
g++ -shared -Wl,-soname,libtest.so -o libtest.so test1.o test2.o link.o -L/usr/local/cuda/lib64 -lcudart
link.o : test1.cu test2.cu test1.h test2.h
nvcc -m64 -arch=sm_20 -dc -Xcompiler '-fPIC' test1.cu test2.cu
nvcc -m64 -arch=sm_20 -Xcompiler '-fPIC' -dlink test1.o test2.o -o link.o
clean :
rm -f testmain test1.o test2.o link.o libtest.so main.o
Không có phiên bản tĩnh của thư viện thời gian chạy cuda, vì vậy bạn không bao giờ mong đợi thấy các ký hiệu thư viện thời gian chạy được bao gồm trong đối tượng hoặc thư viện được chia sẻ của bạn, vì vậy hai chỉnh sửa/bổ sung cuối cùng của bạn là chuỗi màu đỏ ở đây. – talonmies
Ah ok, tôi không biết rằng, điểm tốt. – cmo
@talonmies thực sự bắt đầu với Bộ công cụ CUDA 5.5 cũng có một phiên bản tĩnh của thư viện CUDA Runtime – RoBiK