从 R 调用 CUDA 编译的 .dll

标签 c r cuda

我使用的是 Windows 7 平台。

我在下面逐步描述了我为获取 .dll 文件(通过)、在 R 中动态加载它(通过)和在 R 中调用 .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 编译 objective-c 源代码。

比如:C(dll),部署到R里面调用CUDA dll。

完成后会更新!

编辑 2:

我在下面回答了我自己的问题。我终于可以在 R(WINDOWS 平台)中实现 CUDA

最佳答案

我决定为那些遇到同样困难的人发布我自己的问题的答案。我可以将答案归类为问题的解决方法。

总而言之,我的问题是使用 WINDOWS 平台在 R 中实现 CUDA GPU 并行性。

我看到大多数实现 CUDACRAN 包(不是说全部)都没有用于 WINDOWS 平台的二进制文件。换句话说,如果您尝试在 WINDOWS 中从源代码构建它会失败。我猜它们不是为 WINDOWS 构建的,因为在 WINDOWS 中同时使用 MinGWnvcc 编译器编译和链接 .cu 文件是一种技巧.

NVidia 以VS2010 作为WINDOWS 开发的主要平台,eclipse 插件只支持Linux。虽然,nvcc 编译器支持 -ccbin 选项,可以调用 gcc,但配置“工具链”真的很麻烦。

我的解决方法是在 VS2010 中开发一个 DLL 项目,并使用 VS2010 native 编译器/链接器(即 cl)编译和链接 DLL。

这个 dll 是内部调用 CUDA GPU 并行性的部分。

VS2010 中编译后,我使用 dyn.load() 加载了 dll,并在 中使用 .C 调用了它的函数R.

终于成功了,最终我可以在 WINDOWS 中将 CUDA GPU 并行功能部署到 R > 平台。

我可以在包中部署相同的 .dll,使用 NAMESPACE,并在 CRAN tar ball 中提供 dll 源代码,目的是不违反开源政策。无论如何,这是一种解决方法。

两个重要因素:

1) 使用 extern "C" 在 native C 中部署所有导出函数。

2) 将函数的所有输入变量都视为指针,因为在使用“.C”调用时这是强制性的。

关于从 R 调用 CUDA 编译的 .dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17635531/

相关文章:

r - 使用combn()和bigmemory包生成一个非常大的字符串组合矩阵

r - 在ggplot2中更改颜色填充顺序

r - 在 Rstudio 中使用 rvest 抓取时,我得到了与网络上不同的 html 文本

cuda - CUDA中Malloc函数的效率

cuda - GPU 加速的硬件模拟?

c - 如何以特定方式打印十六进制?

C语言指针

c - SDL 记住最后一个实例的用户输入

c - 使三角形(或通常为正方形)矩阵对称

graphics - 我可以在英特尔集成图形处理器上运行 CUDA 吗?