我有一个现有的应用程序,它使用C ++类,C ++包装器和FORTRAN代码来处理应用程序的计算密集型部分。我想在CUDA中实现FORTRAN的一部分以利用并行化,但我仍然希望访问一些子例程,因此我需要链接CUDA,C ++和FORTRAN代码。
我有三个问题: 1.如何正确链接所有目标文件与Linux终端和Makefile(包含在下面)? 2.在不混淆编译器对设备和主机代码的识别的情况下,在类头中引用CUDA函数的正确方法是什么? 3.将类传递给CUDA就像将类传递给任何其他外部C代码一样?
注意:除了Makefile之外,我没有包含完整的代码(有些代码很长)。如果我需要包含更多内容,请告诉我。
.h文件
#ifndef _DGCPM_H_
#define _DGCPM_H_
extern "C"{
#include <string.h>
#include <zlib.h>
#include <math.h>
}
/* Prototypes of Fortran subroutines */
extern "C" {
void initialize_(float *2Darray);
void advance_(float *2Darray);
//Want "advance" to be implemented in CUDA
}
/* Proper prototype of CUDA call? */
//extern "C" void cudaadvance(float *2Darray);
class DGCPM{
public:
DGCPM(); /* Initialized with defaults setup */
~DGCPM(); /* Free memory */
void advance(float dT); /* Advance model dT seconds */
private:
float **2Darray;
void initialize(float **2Darray);
};
#endif
.C包装
#include "../include/DGCPM.h"
DGCPM::DGCPM(){
initialize();
}
void DGCPM::advance(float dT){
advance_(2Darray[0]);
}
main.C文件
#include <stdlib.h>
#include <stdio.h>
#include <zlib.h>
#include "../include/DGCPM.h"
int main(){
class DGCPM *model;
model=new class DGCPM();
//Write data to class from a file, then
for(int i=0;i<200;i++){
printf("%d\n",i);
model->advance(3600);
//write model state to file;
}
//Close file
return 0;
}
Makefile(注意:“pbo”是FORTRAN代码)
INSTALLDIR=../../lib/
FLAGS=-Wall -g -I ../../amj/include
CFLAGS=$(FLAGS)
CPPFLAGS=$(FLAGS)
FFLAGS=$(FLAGS)
CPP=g++
CC=gcc
FC=g77
PBO_PATH=../ober/for/
VPATH=$(PBO_PATH)
DGCPM_OBJ=DGCPM.o pbo.o
TESTDGCPM_OBJ=testDGCPM.o DGCPM.o pbo.o
ALL_OBJ=$(TESTDGCPM_OBJ)
install: all
mkdir -p $(INSTALLDIR)
cp libDGCPM.a $(INSTALLDIR)
all: libDGCPM.a testDGCPM
libDGCPM.a: $(DGCPM_OBJ)
ar rc $@ $^
testDGCPM: $(TESTDGCPM_OBJ)
$(CPP) -o $@ $^ -L ../../amj/lib -lamjMemory -lg2c -lz
clean:
- rm $(ALL_OBJ)
- rm $(INSTALLDIR)/libDGCPM.a
答案 0 :(得分:3)
您目前没有任何CUDA代码,因此我可能无法提供足够的详细信息。
为你的Qs:
gcc
为.c
,g++
为.cpp
,g77
为.f
,nvcc
和.cu
1}} nvcc
。然后,您可以使用.o
链接所有目标文件__host__
; __device__
和.cu
的.cu文件中显式声明。您有责任不从其他主机代码调用设备代码; 这是我项目的一个例子。可执行文件使用1 .cpp
,1 .a
,一些extern .so
以及一些.cpp
构建。对于icpc
我使用英特尔编译器g++
而不是默认main()
。请注意我的.cu
位于# Compile : bin.cu/b-rbm-gpu.cu
nvcc -ftz true -ccbin icpc -Xcompiler "-Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237" -O3 -Xcompiler "-O3" -gencode arch=compute_20,code=sm_20 -Ilib -c -o bin.cu/b-rbm-gpu.o bin.cu/b-rbm-gpu.cu
# Compile : lib/KTiming.cpp
icpc -Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237 -O3 -MMD -Ilib -c -o lib/KTiming.o lib/KTiming.cpp
# Link : bin.cu/b-rbm-gpu
nvcc -ftz true -ccbin icpc -Xcompiler "-Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237" -O3 -Xcompiler "-O3" -Ilib -Llib bin.cu/b-rbm-gpu.o lib/KTiming.o -lpthread -lm /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_intel_lp64.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_intel_thread.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_core.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_core.a -lcublas -lcurand -lcusparse -o bin.cu/b-rbm-gpu
文件中。
{{1}}
答案 1 :(得分:2)
这是解决方案。要使用CUDA代码,我将引用它,例如
extern "C" void myfunction_(void)
在头文件中,我添加
void myfunction_(void);
在extern“C”原型中。在班级的公共职能中我添加了
void mycudafunction(void);
在C ++包装器中,我添加了
void DGCPM::mycudafunction(){
myfunction_();
}
我现在可以使用这种语法
从主程序中调用“myfunction”model = new class DGCPM();
model->mycudafunction();
我通过将myfunction.o添加到我的所有对象并添加
来修改我的Makefile-L /usr/local/cuda/lib -lcuda -lcudart
我所有的链接说明。
要编译,创建CUDA对象文件(myfunction.o),然后链接,我在终端输入:
nvcc -c myfunction.cu
make
以下是修改后的代码:
.h文件
#ifndef _DGCPM_H_
#define _DGCPM_H_
extern "C"{
#include <string.h>
#include <zlib.h>
#include <math.h>
}
/* Prototypes of Fortran subroutines */
extern "C" {
void initialize_(float *2Darray);
void advance_(float *2Darray);
/*CUDA prototype, can be changed to "cudaadvance" or the like*/
void myfunction_(void);
}
class DGCPM{
public:
DGCPM(); /* Initialized with defaults setup */
~DGCPM(); /* Free memory */
void advance(float dT); /* Advance model dT seconds */
void mycudafunction(void);
private:
float **2Darray;
void initialize(float **2Darray);
};
#endif
.C Wrapper
#include "../include/DGCPM.h"
DGCPM::DGCPM(){
initialize();
}
void DGCPM::advance(float dT){
advance_(2Darray[0]);
}
void DGCPM::mycudafunction(){
myfunction_();
}
main.C文件
#include <stdlib.h>
#include <stdio.h>
#include <zlib.h>
#include "../include/DGCPM.h"
int main(){
class DGCPM *model;
model=new class DGCPM();
//Write data to class from a file, then
for(int i=0;i<200;i++){
printf("%d\n",i);
model->mycudafunction();
model->advance(3600);
//write model state to file;
}
//Close file
return 0;
}
生成文件
INSTALLDIR=../../lib/
FLAGS=-Wall -g -I ../../amj/include
CFLAGS=$(FLAGS)
CPPFLAGS=$(FLAGS)
FFLAGS=$(FLAGS)
CPP=g++
CC=gcc
FC=g77
PBO_PATH=../ober/for/
VPATH=$(PBO_PATH)
DGCPM_OBJ=DGCPM.o pbo.o myfunction.o
TESTDGCPM_OBJ=testDGCPM.o DGCPM.o pbo.o myfunction.o
ALL_OBJ=$(TESTDGCPM_OBJ)
install: all
mkdir -p $(INSTALLDIR)
cp libDGCPM.a $(INSTALLDIR)
all: libDGCPM.a testDGCPM
libDGCPM.a: $(DGCPM_OBJ)
ar rc $@ $^
testDGCPM: $(TESTDGCPM_OBJ)
$(CPP) -o $@ $^ -L ../../amj/lib -lamjMemory -lg2c -lz -L /usr/local/cuda/lib -lcuda -lcudart
clean:
- rm $(ALL_OBJ)
- rm $(INSTALLDIR)/libDGCPM.a
以下是我用来测试的简单CUDA程序。
#include <stdio.h>
__global__ void kernel( void ) {
}
extern "C" void myfunction_(void) {
kernel<<<1,1>>>();
printf( "Hello, World!\n" );
return;
}