我正在使用Windows 7平台。
我将逐步介绍我执行的所有例程,以获取.dll文件(PASS),dyn。在R(PASS)中加载它并在R(FAIL)中唤起.Call函数。
当唤起.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),部署到R里面调用CUDA dll。
完成后会更新!
编辑2:
我在下面回答了我自己的问题。我终于可以在CUDA
(R
)
WINDOWS platform
答案 0 :(得分:4)
对于那些遇到同样困难的人,我决定回答我自己的问题。我可以将答案分类为解决问题的方法。
一天结束,我的问题是使用CUDA
平台在GPU
中实施R
WINDOWS
并行度。
我发现实现CRAN
的大多数CUDA
包(并非全部)都没有WINDOWS平台的二进制文件。换句话说,如果您尝试从WINDOWS
中的源代码构建,则会失败。我猜他们还没有为WINDOWS构建,因为使用WINDOWS
和MinGW
编译器在nvcc
编译和链接.cu文件是一种技巧。
NVidia将VS2010作为WINDOWS
开发的主要平台,eclipse插件仅支持Linux。虽然,nvcc编译器支持-ccbin
选项,可以调用它gcc
,但配置“工具链”真是绝招。
我的解决方法是在VS2010中开发DLL项目,并使用VS2010
本机编译器/链接器cl
来编译和链接DLL。
这个dll是内部调用CUDA GPU
并行性的部分。
在VS2010
中编译后,我使用dyn.load()
加载了dll,并使用.C
中的R
调用了其函数。
它终于奏效了,一天结束时我可以在CUDA
平台中将GPU
R
并行功能部署到WINDOWS
。
我可以使用NAMESPACE在包中部署相同的.dll,并在CRAN tar ball中提供dll源代码,旨在不侵犯开源策略。无论如何,这是一种解决方法。
两个重要因素:
1)使用extern "C"
在本机C中部署所有导出的函数。
2)将函数的所有输入变量视为指针,因为在使用'.C'调用时它是必需的。
答案 1 :(得分:2)
在您的情况下,我要做的是在现有的CUDA R包中非常密切地,它们在CRAN上公开提供,因为它们提供了可行的实现。我相信至少其中一些也建立在Windows上。
使用CUDA的CRAN包中有
等等。有关详情,请参阅CRAN Task View on High-Performance Computing。
我最熟悉的是第一个(也是最老的)。我使用一层代码从R调用C到C,然后用另一层代码调用C到使用NVidia编译器前端编译的CUDA代码。最后一个使用Rcpp从R到C / C ++。我怀疑你的错误是由于试图跳过一步。
答案 2 :(得分:1)
在Windows上通过Visual Studio使用CUDA编译R时,有几件重要的事情。
使用 __ declspec(dllexport)关键字声明C函数(安装 extern&#34; C&#34; )
extern “C” __declspec(dllexport)
使用R(32位或64位)构建相同版本;否则,在R中加载DLL将失败:
加载库失败:%1不是有效的Win32应用程序。
Solution Explorer→项目名称
属性→链接器→输入→附加依赖性
其他详细步骤,您可以参考 NVIDIA blog和ParallelR。