将CUDA集成到C++应用程序中以使用现有的C++类

Joh*_* W. 5 c++ fortran cuda

我有一个现有的应用程序,它使用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
Run Code Online (Sandbox Code Playgroud)

.C包装

#include "../include/DGCPM.h"

DGCPM::DGCPM(){

  initialize();
}


void DGCPM::advance(float dT){

  advance_(2Darray[0]);
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Joh*_* W. 2

这是解决方案。要使用 CUDA 代码,我引用它,例如:

extern "C" void myfunction_(void)
Run Code Online (Sandbox Code Playgroud)

在头文件中,我添加

void myfunction_(void);
Run Code Online (Sandbox Code Playgroud)

在外部“C”原型中。在我添加的类的公共函数中

void mycudafunction(void);
Run Code Online (Sandbox Code Playgroud)

在 C++ 包装器中,我添加

void DGCPM::mycudafunction(){
 myfunction_();
}
Run Code Online (Sandbox Code Playgroud)

我现在可以使用这种类型的语法从主程序调用“myfunction”

model = new class DGCPM();
model->mycudafunction();
Run Code Online (Sandbox Code Playgroud)

我通过将 myfunction.o 添加到所有对象并添加来修改我的 Makefile

-L /usr/local/cuda/lib -lcuda -lcudart 
Run Code Online (Sandbox Code Playgroud)

我所有的链接说明。

为了编译、创建 CUDA 对象文件 (myfunction.o) 和链接,我在终端中键入:

nvcc -c myfunction.cu
make
Run Code Online (Sandbox Code Playgroud)

这是修改后的代码:

.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
Run Code Online (Sandbox Code Playgroud)

.C 包装器

#include "../include/DGCPM.h"

DGCPM::DGCPM(){

  initialize();
}


void DGCPM::advance(float dT){

  advance_(2Darray[0]);
}

void DGCPM::mycudafunction(){
  myfunction_();
}
Run Code Online (Sandbox Code Playgroud)

主.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;
}
Run Code Online (Sandbox Code Playgroud)

生成文件

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
Run Code Online (Sandbox Code Playgroud)

这是我用来测试的简单 CUDA 程序。

#include <stdio.h>

__global__ void kernel( void ) {

}

extern "C" void myfunction_(void) {

    kernel<<<1,1>>>();
    printf( "Hello, World!\n" );
    return;


}
Run Code Online (Sandbox Code Playgroud)