zakim
July 28, 2008, 7:49am
1
Hi guys,
I have just learn how to create shared libraries in linux through the ‘Program Libraries HOWTO’.
For now, I’ve been messing around with CUDA’s template project to turn it into a shared library.
So far what I’ve done:
Change main() in template.cu to cudamain().
I managed to turn it into a static library (a.a) with 'nvcc -lib template.cu -I …/…/common/lib.
Can’t get another program to compile with it. It errors: missing symbol ‘cudamain’ even though it recognises a.a.
However, what I really want to know is how do I make nvcc create a shared library. Thanks :mellow:
nvcc --help says that --shared will produce a shared library. I’ve never tried it as I use CMake + FindCUDA.cmake for compiling which handles all the internal compile commands needed to create the shared library.
You may need to declare cudamain as
extern "C" cudamain() { ... }
in your libs header file if the program you are linking your library to is C++.
If you are on a 64-bit Linux system, you may also need to pass the -fPIC option through to the host compiler:
nvcc --ptxas-options=-v --compiler-options '-fPIC' -o mylib.so --shared mykernel.cu
zakim
July 29, 2008, 12:45am
4
Thanks guys. However, it still doesn’t answer my question on how do I generate the shared library. Is there anyone I can ask regarding this matter?
EDIT: Found this but have not tried it out.
http://www.gpgpu.org/forums/viewtopic.php?p=16723
Thanks guys. However, it still doesn’t answer my question on how do I generate the shared library. Is there anyone I can ask regarding this matter?
EDIT: Found this but have not tried it out.
http://www.gpgpu.org/forums/viewtopic.php?p=16723
[snapback]417396[/snapback]
Did you read my suggestion to use --shared? Did you read seibert’s post where a full command line was given?
To reiterate:
$ nvcc --shared -o libtest.so test.cu --compiler-options '-fPIC'
$ file libtest.so
libtest.so: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), not stripped
$ ldd libtest.so
libcudart.so => /opt/cuda/lib/libcudart.so (0x00002ae61beda000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00002ae61c117000)
libm.so.6 => /lib64/libm.so.6 (0x00002ae61c417000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002ae61c69b000)
libc.so.6 => /lib64/libc.so.6 (0x00002ae61c8a9000)
libdl.so.2 => /lib64/libdl.so.2 (0x00002ae61cbfc000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00002ae61ce01000)
librt.so.1 => /lib64/librt.so.1 (0x00002ae61d01b000)
/lib64/ld-linux-x86-64.so.2 (0x0000003a9ea00000)
If this is not what you are asking for, then please clarify what you mean by “how do I generate the shared library”
zakim
July 29, 2008, 10:28am
6
Hey guys, this is my attempt at it. Errorrreed. Thanks for the help.
hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects$ cp -rf template/ templatelib
hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects$ cd templatelib/
hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects/templatelib$ vim template.cu
----------- I changed main() to cudamain()
hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects/templatelib$ nvcc --shared -o libtest.so template.cu template_kernel.cu template_gold.cpp --compiler-options '-fPIC' -I ../../common/inc/ -I /usr/local/cuda/include/
template_kernel.cu(68): error: identifier "CUT_BANK_CHECKER" is undefined
1 error detected in the compilation of "/tmp/tmpxft_00002803_00000000-15_template_kernel.cpp1.ii".
hpr@hpr-xps:~/NVIDIA_CUDA_SDK/projects/templatelib$
Since you are using CUT_BANK_CHECKER, you need to specify the include (-I) and library directories (-L) for CUT. The makefile sets these so you can open it as an example.
zakim
July 29, 2008, 10:43pm
8
This is from Evan Lezar with final bits from me to make it work
Hi Zaki
I have read your post … and had a look at the commands that CMake generate for the k3d project and I have come up with this.
What I have is two files cuda_functions.h and cuda_functions.cu
cuda_functions.h contains the function declarations that I want to be visible to other apps using the shared library - these must be declared as extern “C” … for example
extern “C” my_function ( int my_parameter );
cuda_functions.cu includes cuda_functions.h and contains the defintion of these functions - for example, the function declared above might be something like
include “cuda_functions.h”
extern “C” my_function ( int my_parameter )
{
dim3 threads ( 8, 8 );
dim3 blocks ( 8, 1, 1);
my_cuda_kernel <<< blocks, threads >>> ( my_param );
}
now you can build a shared library as follows:
nvcc --shared -o libname_of_shared_library.so cuda_functions.cu -I/usr/local/cuda/include -L/usr/local/cuda/lib -lcudart
assuming that you have installed the cuda api to /usr/local/cuda
Any other dependencies such as cutil.h can be added to the above command.
-o specifies the output filename and by convention it starts with lib and shared libraries (in Linux) have a .so extension
-I tells the compiler where to look for the included header files
-L tells the linker where to look for the libraries that are linked and
-l tells the linker to link the libraries - in this case libcudart (note that the lib is left off the name)
Ok - so now you have a shared cuda library :)
The question remains as to how to use it …
Let’s say you have a file main.c from which you wish to call the cuda function my_function
main.c would look something like:
include “cuda_functions.h”
int main()
{
my_function( 5 );
return 0;
}
This program can now be compiled using gcc and linking in the cuda shared library. For example
gcc -o out_file main.c -lname_of_shared_library
where name_of_shared_library is the name as in the preceding section. If the library is not in the same folder as the file you are compiling you may need to specify the location using the -L flag.
Hope this help - please feel free to contact me again if you have any more questions - and perhaps post this on the forum if you get it working so that others with similar problems can be helped :)
Evan
Zaki: This is what I had to do to make it work.
The gcc command above would error out with
gcc -o main main.c -lname_of_shared_library
In file included from main.c:2:
…/cuda_functions.h:2: error: expected identifier or ‘(’ before string constant
make: *** [main] Error 1
What I had to do was to create another cuda_functions.h for gcc, say name it cuda_functions_wo_extern_C.h
with the contents
my_function ( int my_parameter );
I have a very similar issue, but the fix I see posted above doesn’t seem to work.
Here is the command I am using:
nvcc -Xcompiler ‘-fPIC’ --shared -v myFile.cu -o output.so
However, when I use it, I get the following error:
error: relocation R_X86_64_32S against `a local symbol’ can not be used when making a shared object; recompile with -fPIC
The thread above says I need to create a .h file with a declaration of the external C function and include it in my .cu file. I have done this as follows:.
below is the code of myFile.h
#ifndef CUDA_IMAGELOADER_H
#define CUDA_IMAGELOADER_H
extern “C” void launch_cudaCalculations(dim3 grid, dim3 block, int sbytes, float* g_data, float* g_odata, int imgw, int imgh, int tilew, int radius, float threshold, float highlight);
#endif
below is the code snippet from myFile.cu:
#include “myFile.h”
extern “C” void launch_cudaCalculations(dim3 grid, dim3 block, int sbytes, float* in_dev_ptr, float* out_dev_ptr, int cols, int rows)
{ … do stuff … }
Now when I compile I get:
myFile.cu(61): error: more than one instance of overloaded function “launch_cudaCalculations” has “C” linkage
Any ideas?
This is from Evan Lezar with final bits from me to make it work
Zaki: This is what I had to do to make it work.
The gcc command above would error out with
gcc -o main main.c -lname_of_shared_library
In file included from main.c:2:
…/cuda_functions.h:2: error: expected identifier or ‘(’ before string constant
make: *** [main] Error 1
What I had to do was to create another cuda_functions.h for gcc, say name it cuda_functions_wo_extern_C.h
with the contents
my_function ( int my_parameter );
Regarding the extern issue with gcc (zakim). I have since found that following definition in the .h file allows one to use a single file:
[codebox]// the following is needed to allow for the compilation with nvcc as well as gcc
ifdef __cplusplus
#define CHECK_EXT extern "C"
else
#define CHECK_EXT
endif
CHECK_EXT void function_def ();[/codebox]
Thus, I have defined a macro, CHECK_EXT that is blank if a C compiler is used (as opposed to a C++ compiler). This macro is then prefixed to any function definitions.
As far as I can tell this is due to nvcc and gcc defaulting to either C or C++ compilation. If someone has a better explanations, it would be much appreciated.
@muffinman104 : In order to compile with the -fPIC switch using nvcc , one needs to use the --compiler-options -fPIC -shared nvcc options.
For example, the following line is what I use to compile a shared library that is to be built using cublas:
nvcc --shared --compiler-options -fPIC -shared lib_cuda_blas_backend.cu -o libcuda_blas_backend.so -L/usr/local/cuda/lib -lcublas
The shared library libcuda_blas_backend.so can then be linked to another C program as normal.
Please let me know if anything is unclear or you have more questions.
Evan
Thank You for your suggestion.
I have used your this following command to create .so file.
nvcc --shared --compiler-options -fPIC -shared lib_cuda_blas_backend.cu -o libcuda_blas_backend.so -L/usr/local/cuda/lib -lcublas
replaced command -
/usr/local/cuda-7.0/bin/nvcc --shared -Xcompiler -fPIC -shared add.cu -o libcuda_add.so
While linking this file with c file i.e. main.c it showing error
Command-
gcc -o main main.c -llibadd.so
error-
/usr/bin/ld: cannot find -llibadd.so
collect2: ld returned 1 exit status
Please let me know where i am getting wrong.
usually with the -l option you don’t pass the “lib” prefix and the “.so” suffix of libary names. It would be
-ladd or -lcuda_add
Christian
Thank You. I have resolved the issue.