我正在使用C ++,Rcpp和OpenCL开发R软件包。
从.cl文件加载时,构建失败。 但是,当我从const char *内核加载时,它可以工作。
// code build fails
std::ifstream sourceFile("Kernels.cl");
std::string sourceCode( std::istreambuf_iterator<char(sourceFile), (std::istreambuf_iterator<char>()));
cl::Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length()));
// code build passes
cl::Program::Sources source(1, std::make_pair(vadd, strlen(vadd)));
cl::Program program2 = cl::Program(context,source);
在rcpp和OpenCL之间加载OpenCL是否存在问题?
最小示例(全部处理一个R包): Test.cpp
#define __CL_ENABLE_EXCEPTIONS
/* Modified from https://github.com/HandsOnOpenCL/Exercises-Solutions; Simon McIntosh-Smith and Tom Deakin from the University of Bristol*/
#include < /Users/5kd/Documents/TestExample/src/err_code.h >
#include < /Users/5kd/Documents/TestExample/src/cl.hpp >
#include < vector >
#include < stdio >
#include < cstdlib >
#include < string >
#include < iostream >
#include < stream >
#include < /Users/5kd/Documents/TestExample/src/Test_Kernels.h >
#ifndef DEVICE
#define DEVICE CL_DEVICE_TYPE_DEFAULT
#endif
void TestVal1(){
try{
cl::Context context(DEVICE);
cl_int err;
std::ifstream sourceFile("Test_Kernels.cl");
std::string sourceCode( std::istreambuf_iterator<char>(sourceFile), (std::istreambuf_iterator<char>()));
cl::Program::Sources source1(1, std::make_pair(sourceCode.c_str(), sourceCode.length()));
cl::Program program1(context,source1 );
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program1.build(devices);
Rcpp::Rcout << "pass 1\n";
}
catch (cl::Error err) {
Rcpp::Rcout << "Exception\n";
Rcpp::Rcout << "ERROR: "<< err.what() << "(" << err_code(err.err()) << ")" << "\n";
}
};
void TestVal2(){
try{
cl::Context context(DEVICE);
cl_int err;
std::ifstream sourceFile2("vadd.cl");
std::string sourceCode2( std::istreambuf_iterator<char>(sourceFile2), (std::istreambuf_iterator<char>()));
cl::Program::Sources source2(1, std::make_pair(sourceCode2.c_str(), sourceCode2.length()));
cl::Program program2(context,source2 );
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program2.build(devices);
Rcpp::Rcout << "pass 2\n";
}
catch (cl::Error err) {
Rcpp::Rcout << "Exception\n";
Rcpp::Rcout << "ERROR: "<< err.what() << "(" << err_code(err.err()) << ")" << "\n";
}
};
void TestVal3(){
try{
cl::Context context(DEVICE);
cl_int err;
cl::Program::Sources source3(1, std::make_pair(VAdd, strlen(VAdd)));
cl::Program program3(context,source3 );
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program3.build(devices);
Rcpp::Rcout << "pass 3\n";
}
catch (cl::Error err) {
Rcpp::Rcout << "Exception\n";
Rcpp::Rcout << "ERROR: "<< err.what() << "(" << err_code(err.err()) << ")" << "\n";
}
};
SEXP solve_(){
Test opt;
int soln = opt.region(5);
return List::create();
}
int Test::region(int p){
TestVal1();
TestVal2();
TestVal3();
return(p);
};
Test::Test() {};
Test_Kernels.cl
kernel void vadd2( global const float *a , global const float * b ,global float *c ){
int index= get_global_id(0);
c]index] = a[index] + b[index];
}
vadd.cl
__kernel void vadd(
__global float* a,
__global float* b,
__global float* c,
const unsigned int count)
{
int i = get_global_id(0);
if(i < count) {
c[i] = a[i] + b[i];
}
}
Test_Kernels.h
const char * VAdd =" kernel void vadd( global const float *a, global const float *b, global float* c){ int i = get_global_id(0); c[i] = a[i] + b[i]; }";
}
RcppExports.cpp
#include <RcppEigen.h>
#include <Rcpp.h>
using namespace Rcpp;
// solve_
SEXP solve_();
RcppExport SEXP TestExample_solve_() {
BEGIN_RCPP
SEXP __sexp_result;
{
Rcpp::RNGScope __rngScope;
SEXP __result = solve_();
PROTECT(__sexp_result = Rcpp::wrap(__result));
}
UNPROTECT(1);
return __sexp_result;
END_RCPP
}
RcppExports.R
solve_ <- function() {
.Call('TestExample_solve_', PACKAGE = 'TestExample')
}
Test_solve.R
Test_solve <- function() {
opt_ <- get_Test_opts()
.Call('TestExample_solve_', PACKAGE = 'TestExample')
}
主要运行: Test.R
require(RcppEigen)
require(Matrix)
require(TestExample)
t <- Test_solve()
构建使用: R CMD构建TestExample R CMD安装TestExample.tar.gz 跑: R -f Test.R
Output from my run:
> require(RcppEigen)
Loading required package: RcppEigen
> require(Matrix)
Loading required package: Matrix
> require(TestExample)
Loading required package: TestExample
Loading required package: Rcpp
>
>
> t <- Test_solve()
Exception
ERROR: clBuildProgram(CL_BUILD_PROGRAM_FAILURE)
Exception
ERROR: clBuildProgram(CL_BUILD_PROGRAM_FAILURE)
pass 3
答案 0 :(得分:1)
我看不到与Rcpp的关系,因为我能够使用普通的C ++程序重现编译错误:
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <iostream>
#include <fstream>
void TestVal1(){
try{
cl::Context context(CL_DEVICE_TYPE_DEFAULT);
std::ifstream sourceFile("Test_Kernels.cl");
std::string sourceCode( std::istreambuf_iterator<char>(sourceFile), (std::istreambuf_iterator<char>()));
cl::Program::Sources source1(1, std::make_pair(sourceCode.c_str(), sourceCode.length()));
cl::Program program1(context, source1);
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program1.build(devices);
std::cout << "pass 1\n";
}
catch (cl::Error err) {
std::cout << "Exception\n";
std::cout << "ERROR: "<< err.what() << "(" << err.err() << ")" << "\n";
}
}
void TestVal2(){
try{
cl::Context context(CL_DEVICE_TYPE_DEFAULT);
std::ifstream sourceFile("vadd.cl");
std::string sourceCode( std::istreambuf_iterator<char>(sourceFile), (std::istreambuf_iterator<char>()));
cl::Program::Sources source2(1, std::make_pair(sourceCode.c_str(), sourceCode.length()));
cl::Program program2(context, source2);
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program2.build(devices);
std::cout << "pass 2\n";
}
catch (cl::Error err) {
std::cout << "Exception\n";
std::cout << "ERROR: "<< err.what() << "(" << err.err() << ")" << "\n";
}
}
void TestVal3(){
try{
cl::Context context(CL_DEVICE_TYPE_DEFAULT);
const char * VAdd =" kernel void vadd( global const float *a, global const float *b, global float* c){ int i = get_global_id(0); c[i] = a[i] + b[i]; }";
cl::Program::Sources source3(1, std::make_pair(VAdd, strlen(VAdd)));
cl::Program program3(context, source3);
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program3.build(devices);
std::cout << "pass 3\n";
}
catch (cl::Error err) {
std::cout << "Exception\n";
std::cout << "ERROR: "<< err.what() << "(" << err.err() << ")" << "\n";
}
}
int main(){
TestVal1();
TestVal2();
TestVal3();
}
在这两种情况下,内核中都存在简单的语法错误。使用
kernel void vadd2( global const float *a , global const float * b ,global float *c ){
int index= get_global_id(0);
c[index] = a[index] + b[index]; // [ instead of ]
}
和
__kernel void vadd(
__global float* a,
__global float* b,
__global float* c,
const unsigned int count)
{
int i = get_global_id(0);
if(i < count) {
c[i] = a[i] + b[i];
}
} // missing
该示例也可以从Rcpp构建并正常运行:
#define __CL_ENABLE_EXCEPTIONS
#include <Rcpp.h>
#include <CL/cl.hpp>
#include <fstream>
void TestVal1(){
try{
cl::Context context(CL_DEVICE_TYPE_DEFAULT);
std::ifstream sourceFile("Test_Kernels.cl");
std::string sourceCode( std::istreambuf_iterator<char>(sourceFile), (std::istreambuf_iterator<char>()));
cl::Program::Sources source1(1, std::make_pair(sourceCode.c_str(), sourceCode.length()));
cl::Program program1(context,source1 );
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program1.build(devices);
Rcpp::Rcout << "pass 1\n";
}
catch (cl::Error err) {
Rcpp::Rcout << "Exception\n";
Rcpp::Rcout << "ERROR: "<< err.what() << "(" << err.err() << ")" << "\n";
}
}
void TestVal2(){
try{
cl::Context context(CL_DEVICE_TYPE_DEFAULT);
std::ifstream sourceFile2("vadd.cl");
std::string sourceCode2( std::istreambuf_iterator<char>(sourceFile2), (std::istreambuf_iterator<char>()));
cl::Program::Sources source2(1, std::make_pair(sourceCode2.c_str(), sourceCode2.length()));
cl::Program program2(context,source2 );
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program2.build(devices);
Rcpp::Rcout << "pass 2\n";
}
catch (cl::Error err) {
Rcpp::Rcout << "Exception\n";
Rcpp::Rcout << "ERROR: "<< err.what() << "(" << err.err() << ")" << "\n";
}
}
void TestVal3(){
try{
cl::Context context(CL_DEVICE_TYPE_DEFAULT);
const char * VAdd =" kernel void vadd( global const float *a, global const float *b, global float* c){ int i = get_global_id(0); c[i] = a[i] + b[i]; }";
cl::Program::Sources source3(1, std::make_pair(VAdd, strlen(VAdd)));
cl::Program program3(context,source3 );
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
program3.build(devices);
Rcpp::Rcout << "pass 3\n";
}
catch (cl::Error err) {
Rcpp::Rcout << "Exception\n";
Rcpp::Rcout << "ERROR: "<< err.what() << "(" << err.err() << ")" << "\n";
}
}
// [[Rcpp::export]]
void tests(){
TestVal1();
TestVal2();
TestVal3();
}
要编译并运行此文件,请使用:
Sys.setenv(PKG_LIBS = "-lOpenCL")
Rcpp::sourceCpp("kernel_test.cpp")
tests()