Windows 7 プラットフォームを使用しています。
以下に、.dll ファイルを取得する (PASS)、R で dyn.load する (PASS)、R で .Call 関数を呼び出す (FAIL) ために実行するすべてのルーチンを段階的に説明します。
.Call を呼び出すと、次のようになります。
> out<- .Call("rowAND", as.integer(t(m)), nrow(m), ncol(m))
**Error in .Call("rowAND", as.integer(t(m)), nrow(m), ncol(m)) :
C symbol name "rowAND" not in load table**
1) ソースコードの下:
#include <stdio.h>
#include <math.h>
#include <cuda_runtime.h>
#include <cuda.h>
#include <device_launch_parameters.h>
#include <R.h>
#include <Rdefines.h>
#include "cuPrintf.cuh"
#include "cuPrintf.cu"
#include "cuRow.h"
#include "cuError.h"
extern "C" {
SEXP rowAND(SEXP x, SEXP r_nrow, SEXP r_ncol) {
// input:
// x=as.integer(t(m)), vector of integer values from R (t(m) because store values by col)
// r_nrow=nrow(m), scalar
// r_ncol=ncol(m), scalar
//x = coerceVector(x, INTSXP); // force coercion to a matrix of real values
// define deimension
int nrow = asInteger(r_nrow);
int ncol = asInteger(r_ncol);
size_t m_size;
size_t calc_size;
m_size = nrow * ncol * sizeof(int); // m (input)
calc_size = nrow * sizeof(int); // change to nrow/ncol depending on calculation (output)
// R
SEXP r;
PROTECT(r = allocMatrix(INTSXP,nrow,1));
// cuda error variable
cudaError_t err;
// allocate HOST
int *h_m = INTEGER(x);
int *h_calc = INTEGER(r);
// allocate DEVICE
int *d_m = NULL, *d_calc = NULL;
err = cudaMalloc((void **)&d_m, m_size); checkError(err);
err = cudaMalloc((void **)&d_calc, calc_size); checkError(err);
// copy host matrix to device
err = cudaMemcpy(d_m, h_m, m_size, cudaMemcpyHostToDevice); checkError(err);
// Initialize cuPrintf -- DEBUGGING
cudaPrintfInit();
dim3 numBlocks(nrow,1,1); // blocks
dim3 threadsPerBlock(1,1,1); // 1 thread per block
rowOR<<<numBlocks, threadsPerBlock,0,0>>>(d_m, d_calc, ncol); // main call
// Terminate cuPrintf -- DEBUGGING
cudaPrintfDisplay (stdout, true);
cudaPrintfEnd ();
err = cudaGetLastError(); checkError(err);
// Copy the device result vector in device memory to the host result vector
err = cudaMemcpy(h_calc, d_calc, calc_size, cudaMemcpyDeviceToHost); checkError(err);
// Free device global memory
err = cudaFree(d_m); checkError(err);
err = cudaFree(d_calc); checkError(err);
// Reset the device
err = cudaDeviceReset();
UNPROTECT(1);
return r;
}
2) オブジェクト (.obj) を生成する nvcc を使用して、.cu ファイルをコンパイルします。したがって、ライブラリをリンクします (PASS)。ここでは問題ありません。.dll ファイルが生成されます。
3) R コマンドを使用して .dll をロードするとき: dyn.load IT PASS。ロードされた .dll は次の場所に表示されますgetLoadedDLLs()
。
> getLoadedDLLs()
Filename Dynamic.Lookup
base base FALSE
methods C:/Revolution/R-Community-6.2/R-2.15.3/library/methods/libs/i386/methods.dll FALSE
Revobase C:/Revolution/R-Community-6.2/R-2.15.3/library/Revobase/libs/i386/Revobase.dll TRUE
tools C:/Revolution/R-Community-6.2/R-2.15.3/library/tools/libs/i386/tools.dll FALSE
grDevices C:/Revolution/R-Community-6.2/R-2.15.3/library/grDevices/libs/i386/grDevices.dll FALSE
stats C:/Revolution/R-Community-6.2/R-2.15.3/library/stats/libs/i386/stats.dll FALSE
cuRow C:/Users/msn/Documents/Visual Studio 2010/Projects/R_C/R_C/Debug/cuRow.dll TRUE
4)ここに問題があります:関数rowANDがロードされているかどうかを確認すると、FALSEが表示されます:
> is.loaded("rowAND")
[1] FALSE
>
したがって、明らかに、.Call を実行すると失敗します (ロードされていないため)。
> path.dll<-'C:/Users/msn/Documents/Visual Studio 2010/Projects/R_C/R_C/Debug'
> dyn.load(file.path(path.dll,paste0("cuRow", .Platform$dynlib.ext)))
> nrow<-10
> ncol<-3
> m<-matrix(sample(c(0,1),nrow*ncol,replace=TRUE),nrow,ncol)
> out<- .Call("rowAND", as.integer(t(m)), nrow(m), ncol(m))
Error in .Call("rowAND", as.integer(t(m)), nrow(m), ncol(m)) :
C symbol name "rowAND" not in load table
ソース コードでは関数が正しく定義されているように見えますが、読み込まれたライブラリでは「見えません」。
ここで何が欠けていますか?前もって感謝します!
編集:
@Dirkの部分的な回答に基づいて、Cによって呼び出されるCUDA dllプロジェクトを作成しようとします。したがって、標準のR CMD SHLIBを使用してターゲットCソースをコンパイルできます。
のように: C (dll)、内部で CUDA dll を呼び出す R にデプロイされます。
完了したら更新します!
編集2:
私は以下の私自身の質問に答えました。( )でようやくCUDA
実装できましたR
WINDOWS platform