5

アプリケーションの計算負荷の高い部分に C++ クラス、C++ ラッパー、および FORTRAN コードを使用する既存のアプリケーションがあります。FORTRAN の一部を CUDA に実装して並列化を利用したいと考えていますが、サブルーチンのいくつかにはまだアクセスしたいので、CUDA、C++、および FORTRAN コードをリンクする必要があります。

3 つの質問があります。 1. すべてのオブジェクト ファイルを Linux ターミナルおよび Makefile (以下に含まれています) と正しくリンクするにはどうすればよいですか? 2. デバイスとホスト コードのコンパイラの認識を混乱させることなく、クラス ヘッダーで CUDA 関数を参照する適切な方法は何ですか? 3. クラスを他の外部 C コードに渡すのと同じように、クラスを CUDA に渡しますか?

注: 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
4

2 に答える 2

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 ラッパー

#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;


}
于 2013-07-22T21:16:06.857 に答える