2013-06-24 41 views
11

Mục tiêu:CUDA chia sẻ liên kết thư viện: tài liệu tham khảo không xác định để cudaRegisterLinkedBinary

  1. tạo ra một thư viện chia sẻ chứa hạt nhân CUDA của tôi mà có một wrapper CUDA-free/tiêu đề.
  2. tạo tệp thực thi test cho thư viện được chia sẻ.

Vấn đề

  1. chia sẻ thư viện MYLIB.so dường như biên dịch tốt. (không vấn đề gì).
  2. Lỗi trong việc kết nối:

./libMYLIB.so: undefined reference to __cudaRegisterLinkedBinary_39_tmpxft_000018cf_00000000_6_MYLIB_cpp1_ii_74c599a1

đơn giản makefile:

libMYlib.so : MYLIB.o 
    g++ -shared -Wl,-soname,libMYLIB.so -o libMYLIB.so MYLIB.o -L/the/cuda/lib/dir -lcudart 


MYLIB.o : MYLIB.cu MYLIB.h 
    nvcc -m64 -arch=sm_20 -dc -Xcompiler '-fPIC' MYLIB.cu -o MYLIB.o -L/the/cuda/lib/dir -lcudart 


test : test.cpp libMYlib.so 
     g++ test.cpp -o test -L. -ldl -Wl,-rpath,. -lMYLIB -L/the/cuda/lib/dir -lcudart 

thực

nm libMYLIB.so cho thấy tất cả CUDA api funct ion là "biểu tượng không xác định":

  U __cudaRegisterFunction 
     U __cudaRegisterLinkedBinary_39_tmpxft_0000598c_00000000_6_CUPA_cpp1_ii_74c599a1 
     U cudaEventRecord 
     U cudaFree 
     U cudaGetDevice 
     U cudaGetDeviceProperties 
     U cudaGetErrorString 
     U cudaLaunch 
     U cudaMalloc 
     U cudaMemcpy 

Vì vậy CUDA bằng cách nào đó đã không được liên kết với thư viện chia sẻ MYLIB.so tôi đang thiếu gì?


CUDA thậm chí không được liên kết với đối tượng tập tin bằng cách nào đó:

nm MYLIB.o

  U __cudaRegisterFunction 
     U __cudaRegisterLinkedBinary_39_tmpxft_0000598c_00000000_6_CUPA_cpp1_ii_74c599a1 
     U cudaEventRecord 
     U cudaFree 
     U cudaGetDevice 
     U cudaGetDeviceProperties 
     U cudaGetErrorString 
     U cudaLaunch 
     U cudaMalloc 
     U cudaMemcpy 

(tương tự như trên)

+0

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

+0

Ah ok, tôi không biết rằng, điểm tốt. – cmo

+3

@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

Trả lời

10

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:

  1. 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í .
  2. 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 
+2

Vấn đề vẫn còn. Theo ví dụ của bạn, mọi thứ biên dịch suôn sẻ cho đến bước cuối cùng - trong việc tạo tệp thi hành thử nghiệm, tại thời điểm đó, lỗi '__cudaRegisterLinkedBinary_39_tmpxft ...' được ném ra, như được mô tả trước đây. – cmo

+0

Tôi không chắc chắn vấn đề có thể là gì. Nó có vẻ hoạt động hoàn hảo cho tôi. Bạn có làm theo các bước của tôi và sử dụng các tệp của tôi chính xác không? Bạn đang sử dụng cuda 5.0? –

+0

@MatthewParks Tôi có cùng vấn đề với __cudaRegisterLinkedBinary_39_tmpxft ..., bạn đã giải quyết được rằng –

0

bạn đã cố gắng vô hiệu hóa explictly đang thiết bị định vị? tức là -rdc=false? Tôi nhận được số này undefined reference to __cudaRegisterLinkedBinaryWhatever với -rdc=true và nó đã biến mất khi tôi xóa nó. Mặc dù tôi không đủ chuyên gia để giải thích chính xác những gì đang xảy ra với điều đó.

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