Using RViennaCL for matrix multiplication - r

I'm a newbie using the RViennaCL package, trying to do GPU matrix multiplication.
Trying a simple case I created a cpp file inside the src folder within the package I created (gpuUtils), with this code:
#include "viennacl/ocl/backend.hpp"
#include "viennacl/linalg/prod.hpp"
#include "viennacl/tools/random.hpp"
#include "viennacl/matrix.hpp"
//' PU matrix multiplication
//'
//' #export
// [[Rcpp::export]]
SEXP matMult(){
viennacl::tools::uniform_random_numbers<float> randomNumber;
viennacl::matrix<float> vcl_A(400, 400);
viennacl::matrix<float> vcl_B(400, 400);
for (unsigned int i = 0; i < vcl_A.size1(); ++i)
for (unsigned int j = 0; j < vcl_A.size2(); ++j)
vcl_A(i,j) = randomNumber();
for (unsigned int i = 0; i < vcl_B.size1(); ++i)
for (unsigned int j = 0; j < vcl_B.size2(); ++j)
vcl_B(i,j) = randomNumber();
viennacl::matrix<float> vcl_C = viennacl::linalg::prod(vcl_A, vcl_B);
return Rcpp::wrap(vcl_C);
}
Then I build the package:
$ R CMD build gpuUtils
* checking for file ‘gpuUtils/DESCRIPTION’ ... OK
* preparing ‘gpuUtils’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
* building ‘gpuUtils_0.0.0.9000.tar.gz’
But when trying to install it I get:
$ R CMD INSTALL gpuUtils_0.0.0.9000.tar.gz
* installing to library ‘/home/usr/R’
* installing *source* package ‘gpuUtils’ ...
** libs
g++ -I/opt/ohpc/pub/libs/gnu7/R/3.4.2/lib64/R/include -DNDEBUG -I/usr/local/cuda-9.0/include/ -I"/home/usr/R/Rcpp/include" -I"/home/usr/R/RViennaCL/include" -I/usr/local/include -fpic -g -O2 -c gpuUtils.cpp -o gpuUtils.o
In file included from /home/usr/R/Rcpp/include/RcppCommon.h:195:0,
from /home/usr/R/Rcpp/include/Rcpp.h:27,
from /home/usr/R/RViennaCL/include/viennacl/ocl/forwards.h:29,
from /home/usr/R/RViennaCL/include/viennacl/ocl/context.hpp:36,
from /home/usr/R/RViennaCL/include/viennacl/ocl/backend.hpp:26,
from gpuUtils.cpp:1:
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h: In instantiation of ‘SEXPREC* Rcpp::internal::wrap_dispatch_unknown_iterable(const T&, Rcpp::traits::false_type) [with T = viennacl::matrix<float, viennacl::row_major>; SEXP = SEXPREC*; Rcpp::traits::false_type = Rcpp::traits::integral_constant<bool, false>]’:
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:732:43: required from ‘SEXPREC* Rcpp::internal::wrap_dispatch_unknown(const T&, Rcpp::traits::false_type) [with T = viennacl::matrix<float, viennacl::row_major>; SEXP = SEXPREC*; Rcpp::traits::false_type = Rcpp::traits::integral_constant<bool, false>]’
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:770:41: required from ‘SEXPREC* Rcpp::internal::wrap_dispatch_eigen(const T&, Rcpp::traits::false_type) [with T = viennacl::matrix<float, viennacl::row_major>; SEXP = SEXPREC*; Rcpp::traits::false_type = Rcpp::traits::integral_constant<bool, false>]’
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:787:39: required from ‘SEXPREC* Rcpp::internal::wrap_dispatch_unknown_importable(const T&, Rcpp::traits::false_type) [with T = viennacl::matrix<float, viennacl::row_major>; SEXP = SEXPREC*; Rcpp::traits::false_type = Rcpp::traits::integral_constant<bool, false>]’
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:807:52: required from ‘SEXPREC* Rcpp::internal::wrap_dispatch(const T&, Rcpp::traits::wrap_type_unknown_tag) [with T = viennacl::matrix<float, viennacl::row_major>; SEXP = SEXPREC*]’
/home/usr/R/Rcpp/include/Rcpp/internal/wrap_end.h:30:38: required from ‘SEXPREC* Rcpp::wrap(const T&) [with T = viennacl::matrix<float, viennacl::row_major>; SEXP = SEXPREC*]’
gpuUtils.cpp:25:26: required from here
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:523:17: error: static assertion failed: cannot convert type to SEXP
static_assert(!sizeof(T), "cannot convert type to SEXP");
^~~~~~~~~~~~~
make: *** [gpuUtils.o] Error 1
ERROR: compilation failed for package ‘gpuUtils’
* removing ‘/home/usr/R/gpuUtils’
* restoring previous ‘/home/usr/R/gpuUtils’
Which indicates that viennacl::matrix need its own wrap function to be written.
So I tried to follow this very nice vignette for custom templating as and wrap functions within Rcpp, adapting it to the viennacl::matrix case.
Here's my cpp code:
#include <RcppCommon.h>
#include "viennacl/ocl/backend.hpp"
#include "viennacl/matrix.hpp"
// [[Rcpp::plugins("cpp11")]]
// Provide Forward Declarations
namespace Rcpp {
namespace traits{
// Setup non-intrusive extension via template specialization for
// 'viennacl' class
// Support for wrap
template <typename T> SEXP wrap(const viennacl::matrix<T> & obj);
// Support for as<T>
template <typename T> class Exporter< viennacl::matrix<T> >;
}
}
#include <Rcpp.h>
// Define template specializations for as<> and wrap
namespace Rcpp {
namespace traits{
// Defined wrap case
template <typename T> SEXP wrap(const viennacl::matrix<T> & obj){
const int RTYPE = Rcpp::traits::r_sexptype_traits<T>::rtype ;
return Rcpp::Matrix< RTYPE >(obj.begin(), obj.end());
};
// Defined as< > case
template<typename T> class Exporter< viennacl::matrix<T> > {
typedef typename viennacl::matrix<T> OUT ;
// Convert the type to a valid rtype.
const static int RTYPE = Rcpp::traits::r_sexptype_traits< T >::rtype ;
Rcpp::Matrix<RTYPE> mat;
public:
Exporter(SEXP x) : mat(x) {
if (TYPEOF(x) != RTYPE)
throw std::invalid_argument("Wrong R type for mapped 2D array");
}
OUT get() {
// Need to figure out a way to perhaps do a pointer pass?
OUT x(mat.size());
std::copy(mat.begin(), mat.end(), mat.begin());
return x;
}
};
}
}
//' viennacl matrix templating
//'
//' #export
// [[Rcpp::export]]
void matTemplate(Rcpp::NumericMatrix in_mat){
viennacl::matrix<double> viennacl_mat = Rcpp::as< viennacl::matrix<double> >(in_mat);
Rcpp::NumericMatrix out_mat = Rcpp::wrap(viennacl_mat);
}
Builds fine:
$ R CMD build gpuUtils
* checking for file ‘gpuUtils/DESCRIPTION’ ... OK
* preparing ‘gpuUtils’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
* building ‘gpuUtils_0.0.0.9000.tar.gz’
But still getting the same error:
$ R CMD INSTALL gpuUtils_0.0.0.9000.tar.gz
* installing to library ‘/home/usr/R’
* installing *source* package ‘gpuUtils’ ...
** libs
g++ -I/opt/ohpc/pub/libs/gnu7/R/3.4.2/lib64/R/include -DNDEBUG -I/usr/local/cuda-9.0/include/ -I"/home/usr/R/Rcpp/include" -I"/home/usr/R/RViennaCL/include" -I/usr/local/include -fpic -g -O2 -c gpuUtils.cpp -o gpuUtils.o
In file included from /home/usr/R/Rcpp/include/RcppCommon.h:195:0,
from gpuUtils.cpp:1:
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h: In instantiation of ‘SEXPREC* Rcpp::internal::wrap_dispatch_unknown_iterable(const T&, Rcpp::traits::false_type) [with T = viennacl::matrix<double, viennacl::row_major>; SEXP = SEXPREC*; Rcpp::traits::false_type = Rcpp::traits::integral_constant<bool, false>]’:
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:732:43: required from ‘SEXPREC* Rcpp::internal::wrap_dispatch_unknown(const T&, Rcpp::traits::false_type) [with T = viennacl::matrix<double, viennacl::row_major>; SEXP = SEXPREC*; Rcpp::traits::false_type = Rcpp::traits::integral_constant<bool, false>]’
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:770:41: required from ‘SEXPREC* Rcpp::internal::wrap_dispatch_eigen(const T&, Rcpp::traits::false_type) [with T = viennacl::matrix<double, viennacl::row_major>; SEXP = SEXPREC*; Rcpp::traits::false_type = Rcpp::traits::integral_constant<bool, false>]’
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:787:39: required from ‘SEXPREC* Rcpp::internal::wrap_dispatch_unknown_importable(const T&, Rcpp::traits::false_type) [with T = viennacl::matrix<double, viennacl::row_major>; SEXP = SEXPREC*; Rcpp::traits::false_type = Rcpp::traits::integral_constant<bool, false>]’
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:807:52: required from ‘SEXPREC* Rcpp::internal::wrap_dispatch(const T&, Rcpp::traits::wrap_type_unknown_tag) [with T = viennacl::matrix<double, viennacl::row_major>; SEXP = SEXPREC*]’
/home/usr/R/Rcpp/include/Rcpp/internal/wrap_end.h:30:38: required from ‘SEXPREC* Rcpp::wrap(const T&) [with T = viennacl::matrix<double, viennacl::row_major>; SEXP = SEXPREC*]’
gpuUtils.cpp:68:56: required from here
/home/usr/R/Rcpp/include/Rcpp/internal/wrap.h:523:17: error: static assertion failed: cannot convert type to SEXP
static_assert(!sizeof(T), "cannot convert type to SEXP");
^~~~~~~~~~~~~
make: *** [gpuUtils.o] Error 1
ERROR: compilation failed for package ‘gpuUtils’
* removing ‘/home/usr/R/gpuUtils’
* restoring previous ‘/home/usr/R/gpuUtils’

Short answer: yes. RViennaCl only provides the ViennaCl headers but no as() and wrap() functions for communication between R and C++ data structures. And the gpuR package, which uses RViennaCl, uses a different approach by exposing suitable objects to R with appropriate functions acting on these objects. Of course, you can use these objects to do matrix multiplication on the GPU.
So you would have to write these functions yourself if you are interested in communication between R and ViennaCl data structures. This is not a simple task, though, since RViennaCL patches the ViennaCL headers to include Rcpp.h (e.g. https://github.com/cdeterman/RViennaCL/blob/master/inst/include/viennacl/ocl/backend.hpp#L29). This makes it impossible to use the usual extension mechanisms as you are trying above. I think it would be sufficient for RViennaCL to include RcppCommon.h, this way making extensions possible. But I have not tried that. I have filed https://github.com/cdeterman/RViennaCL/issues/4 for this.
Instead of writing as() and wrap() for ViennaCL you could also combine available converters with a package that converts to and from R data structures. So in a package that uses LinkingTo: Rcpp, RViennaCL, RcppEigen this function works for me:
#define VIENNACL_HAVE_EIGEN
#include <RcppEigen.h>
#include <viennacl/ocl/backend.hpp>
#include <viennacl/matrix.hpp>
//' viennacl matrix crossprod
//'
//' #export
// [[Rcpp::export]]
Eigen::MatrixXd vclCrossprod(const Eigen::MatrixXd &in_densematrix){
int rows = in_densematrix.rows();
int cols = in_densematrix.cols();
viennacl::matrix<double> viennacl_densematrix(rows, cols);
viennacl::copy(in_densematrix, viennacl_densematrix);
viennacl::matrix<double> viennacl_result = viennacl::linalg::prod(
viennacl::trans(viennacl_densematrix),
viennacl_densematrix);
Eigen::MatrixXd eigen_result(cols, cols);
viennacl::copy(viennacl_result, eigen_result);
return eigen_result;
}
However, for the examples I tried, this approach is not really efficient. This might change if you are doing something more complicated than matrix multiplication.
Alternatively you could try RcppArrayFire, which I am working on, if you are mainly interested in GPGPU and not ViennaCl in particular.

Related

Using custom Rcpp class in rcpp-function in an R-package. Both class and function are defined in the same .cpp file

I'm trying to speed up a loop over the dimensions of an R-array using Rcpp.
The array class is from the rcpp-gallery: (https://github.com/RcppCore/rcpp-gallery/blob/gh-pages/src/2014-03-21-simple-array-class.Rmd
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace Rcpp ;
/*
******************************************************************************
Offset and Array classes based on code by Romain Francois copied from
http://comments.gmane.org/gmane.comp.lang.r.rcpp/5932 on 2014-01-07.
******************************************************************************
*/
class Offset{
private:
IntegerVector dim ;
public:
Offset( IntegerVector dim ) : dim(dim) {}
int operator()( IntegerVector ind ){
int ret = ind[0] ;
int offset = 1 ;
for(int d=1; d < dim.size(); d++) {
offset = offset * dim[d-1] ;
ret = ret + ind[d] * offset ;
}
return ret ;
} ;
IntegerVector getDims() const {
return(dim) ;
};
} ;
class Array : public NumericVector {
private:
// NumericVector value;
Offset dims ;
public:
//Rcpp:as
Array( SEXP x) : NumericVector(x),
dims( (IntegerVector)((RObject)x).attr("dim") ) {}
Array( NumericVector x, Offset d ): NumericVector(x),
dims(d) {}
Array( Dimension d ): NumericVector( d ), dims( d ) {}
IntegerVector getDims() const {
return(dims.getDims());
};
NumericVector getValue() const {
return(*((NumericVector*)(this)));
};
inline double& operator()( IntegerVector ind) {
int vecind = dims(ind);
NumericVector value = this->getValue();
return value(vecind);
} ;
// change dims without changing order of elements (!= aperm)
void resize(IntegerVector newdim) {
int n = std::accumulate((this->getDims()).begin(), (this->getDims()).end(), 1,
std::multiplies<int>());
int nnew = std::accumulate(newdim.begin(), newdim.end(), 1,
std::multiplies<int>());
if(n != nnew) stop("old and new old dimensions don't match.");
this->dims = Offset(newdim);
} ;
} ;
namespace Rcpp {
// wrap(): converter from Array to an R array
template <> SEXP wrap(const Array& A) {
IntegerVector dims = A.getDims();
//Dimension dims = A.getDims();
Vector<REALSXP> x = A;
x.attr( "dim" ) = wrap(dims);
return x;
}
}
// [[Rcpp::export]]
int runloop(Array& myarray) {
IntegerVector myarrayDims = myarray.getDims();
for (int j = 0; j < myarrayDims[1]; j++) {
for (int k = 0; k < myarrayDims[2]; k++) {
for (int l = 0; l < myarrayDims[3]; l++) {
for (int i = 0; i < myarrayDims[0]; i++) {
myarray({i, j, k, l}) = i + j + k +l;
}
}
}
}
return 0;
}
Sourcing and executing this code from an interactive R session works as intended.
library(Rcpp)
sourceCpp(file.path(".", "minimalExample.cpp"))
inputArray <- array(data = rnorm(10^4), dim = c(10, 10, 10, 10))
runloop(inputArray)
inputArray
But when I move the .cpp file into the src-folder of my R package structure, the build fails, because the class Array is not recognized (see screenshot of build errors)
The content of the RcppExports.cpp after the failed build is as follows:
// Generated by using Rcpp::compileAttributes() -> do not edit by hand
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace Rcpp;
// runloop
int runloop(Array& myarray);
RcppExport SEXP _foobar_runloop(SEXP myarraySEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< Array& >::type myarray(myarraySEXP);
rcpp_result_gen = Rcpp::wrap(runloop(myarray));
return rcpp_result_gen;
END_RCPP
}
static const R_CallMethodDef CallEntries[] = {
{"_foobar_runloop", (DL_FUNC) &_foobar_runloop, 1},
{NULL, NULL, 0}
};
RcppExport void R_init_foobar(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}
How can i get my simple loop running?
Thanks :)
ps: my sessionInfo() in R-Studio returns:
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19041)
Matrix products: default
locale:
[1] LC_COLLATE=English_Germany.1252 LC_CTYPE=English_Germany.1252 LC_MONETARY=English_Germany.1252 LC_NUMERIC=C
[5] LC_TIME=English_Germany.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] Rcpp_1.0.5
loaded via a namespace (and not attached):
[1] compiler_3.6.1 tools_3.6.1
There is a saying that you need to walk before you can run. You missed the jogging step between the walk and the sprint ;-).
Having code that compiles in a single function that you source is not the same as having it in a full-blown package. What you desire to do can be done and has been done. In short, while you have the code wrote in the source file, it also needs to be present in the generated file src/RcppExports.cpp.
One trick you are missing now is described in the Rcpp Attributes vignette in the section Types in Generated Code, and I quote (editing out markdown/latex)
Types in Generated Code
In some cases the signatures of the C++ functions that are generated within
RcppExports.cpp may have additional type requirements beyond the core
standard library and Rcpp types (e.g. CharacterVector,
NumericVector, etc.). Examples might include convenience typedefs,
as/wrap handlers for marshaling between custom types and SEXP, or types
wrapped by the Rcpp XPtr template.
In this case, you can create a header file that contains these type definitions
(either defined inline or by including other headers) and have this header
file automatically included in RcppExports.cpp. Headers named with
the convention pkgname_types are automatically included along with
the generated C++ code. For example, if your package is named fastcode
then any of the following header files would be automatically included in
RcppExports.cpp:
src/fastcode_types.h
src/fastcode_types.hpp
inst/include/fastcode_types.h
inst/include/fastcode_types.hpp
[...]

Exposing a C object from an external C library from C++ to R and back again using Rcpp

This is a follow-up question on this one: Exposing a C struct with Rcpp?
#DirkEddelbuettel justly criticized that aforementioned question as being too broad in scope so I am here trying to be more specific in my goals, while providing some actual code exemplifying my attempt at this problem.
Description of the problem
First thing: please note that I use (somewhat unfortunately, I will change it eventually) two similar names in my code: GLuint and Gluint.
I'm trying to wrap this C OpenGL functionality in R (taken from here: OpenGL
Textures objects and parameters):
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
Approach
I am using Rcpp to achieve these goals:
Provide a way of allocating the Gluint object from R; perhaps by instantiating an S4 object that wraps the C object (GLuint tex) inside?
Then, have an R exposed function named gl_gen_textures that takes an integer and that object mentioned in 1. Internally, this function gl_gen_textures accesses the memory address of the GLuint C object and passes it on to glGenTextures (C library function).
Eventually provide a way of destroying the Gluint object created in R and along with it the internal GLuint C object.
Actual code
#include <Rcpp.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
using namespace Rcpp;
class Gluint {
public:
Gluint() {}
GLuint obj;
};
RCPP_MODULE(gluint_module) {
class_<Gluint>("Gluint")
.constructor()
.field("obj", &Gluint::obj)
;
}
//' #export
// [[Rcpp::export]]
void gl_gen_textures(unsigned int n, Gluint& tex) {
uint32_t _n;
_n = (uint32_t) n; // Convert unsigned int to uint32_t.
glGenTextures((GLsizei) _n, &(tex.obj));
}
Errors
Currently this code does not compile. I'm getting these errors:
And here's a snippet of the function gl_gen_textures as generated in Rcpp::Exports.cpp lines 136-146:
// gl_gen_textures
void gl_gen_textures(unsigned int n, Gluint& tex);
RcppExport SEXP _glfw_gl_gen_textures(SEXP nSEXP, SEXP texSEXP) {
BEGIN_RCPP
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< unsigned int >::type n(nSEXP);
Rcpp::traits::input_parameter< Gluint& >::type tex(texSEXP);
gl_gen_textures(n, tex);
return R_NilValue;
END_RCPP
}

How to return an Rcpp List to a C function

Question
In an R package, how do I return an Rcpp::List to a C function?
Example
I have a package hosted on my github page to illustrate the requirement.
It contains an R function, which calls a C function, which I would like to call the C++ function to retrieve the list.
R
#' #useDynLib crcpp c_ask_for_list
r_ask_for_list <- function() {
.Call(c_ask_for_list)
}
C
#include <Rinternals.h>
SEXP c_ask_for_list (){
SEXP l = PROTECT(allocVector(VECSXP, 1));
//l = rcpp_create_list(); // Call the C++ function to create the list
UNPROTECT(1);
return(l);
}
C++
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
extern "C" SEXP rcpp_create_list() {
Rcpp::List l(1);
l[0] = "foo";
return l;
}
If I uncomment the l = rcpp_create_list() line in the C function the program crashes.
Thanks to all the pointers I have the program working as intended. The full structure now is
R
#' #useDynLib crcpp c_ask_for_list
#' #export
r_ask_for_list <- function() {
.Call("c_ask_for_list", packages = "crcpp")
}
C
file: c_ask_for_list.h
#ifndef CRCPP_H
#define CRCPP_H
#include <Rinternals.h>
#ifdef __cplusplus
extern "C" {
#endif
SEXP rcpp_create_list();
#ifdef __cplusplus
}
#endif
#endif /* CRCPP_H */
file: c_ask_for_list.c
#include "c_ask_for_list.h"
SEXP c_ask_for_list () {
SEXP l = _crcpp_rcpp_create_list(); // Call the C++ function to create the list
return(l);
}
C++
file: rcpp_create_list.cpp
#include <Rcpp.h>
using namespace Rcpp;
//' #importFrom Rcpp evalCpp
//' #export
// [[Rcpp::export]]
SEXP rcpp_create_list() {
Rcpp::List l(2);
l[0] = "foo";
l[1] = "bar";
return l;
}

move semantics for different qt versions

Am beginner in move semantics and I'm confused by compilation result. When I use qt 5.5.1 all are okey, but when I use qt 4.8.7 I have build errors. I'm trying to build the following code:
struct TResource
{
int _resource_id = 18;
};
typedef std::vector<std::unique_ptr<TResource>> TResources;
struct TChannel
{
QString _title;
TResources _ress;
};
typedef std::vector<TChannel> TChanneles;
int main(int , char **)
{
TChannel channel;
TChanneles chnls;
//Creating some channel resorces and place it to the vector
// .......
chnls.push_back(std::move(channel));
return 0;
}
The error messages are following:
g++ -c -m64 -pipe -std=c++0x -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. -o main.o main.cpp
In file included from /usr/include/c++/5/bits/stl_tempbuf.h:60:0,
from /usr/include/c++/5/bits/stl_algo.h:62,
from /usr/include/c++/5/algorithm:62,
from /usr/include/qt4/QtCore/qglobal.h:68,
from /usr/include/qt4/QtCore/qnamespace.h:45,
from /usr/include/qt4/QtCore/qobjectdefs.h:45,
from /usr/include/qt4/QtCore/qobject.h:47,
from /usr/include/qt4/QtCore/qcoreapplication.h:45,
from /usr/include/qt4/QtCore/QCoreApplication:1,
from main.cpp:1:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<TResource>; _Args = {const std::unique_ptr<TResource, std::default_delete<TResource> >&}]’:
/usr/include/c++/5/bits/stl_uninitialized.h:75:18: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<TResource>*, std::vector<std::unique_ptr<TResource> > >; _ForwardIterator = std::unique_ptr<TResource>*; bool _TrivialValueTypes = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:126:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<TResource>*, std::vector<std::unique_ptr<TResource> > >; _ForwardIterator = std::unique_ptr<TResource>*]’
/usr/include/c++/5/bits/stl_uninitialized.h:281:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<TResource>*, std::vector<std::unique_ptr<TResource> > >; _ForwardIterator = std::unique_ptr<TResource>*; _Tp = std::unique_ptr<TResource>]’
/usr/include/c++/5/bits/stl_vector.h:322:31: required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<TResource>; _Alloc = std::allocator<std::unique_ptr<TResource> >]’
main.cpp:11:8: required from ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = TChannel; _Args = {TChannel&}]’
/usr/include/c++/5/bits/stl_uninitialized.h:75:18: [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/5/bits/stl_uninitialized.h:281:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = TChannel*; _ForwardIterator = TChannel*; _Tp = TChannel]’
/usr/include/c++/5/bits/stl_uninitialized.h:303:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = TChannel*; _ForwardIterator = TChannel*; _Allocator = std::allocator<TChannel>]’
/usr/include/c++/5/bits/vector.tcc:422:8: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {TChannel}; _Tp = TChannel; _Alloc = std::allocator<TChannel>]’
/usr/include/c++/5/bits/vector.tcc:101:23: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {TChannel}; _Tp = TChannel; _Alloc = std::allocator<TChannel>]’
/usr/include/c++/5/bits/stl_vector.h:932:21: required from ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = TChannel; _Alloc = std::allocator<TChannel>; std::vector<_Tp, _Alloc>::value_type = TChannel]’
main.cpp:26:39: required from here
/usr/include/c++/5/bits/stl_construct.h:75:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = TResource; _Dp = std::default_delete<TResource>]’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
In file included from /usr/include/c++/5/memory:81:0,
from main.cpp:2:
/usr/include/c++/5/bits/unique_ptr.h:356:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^
Makefile:203: recipe for target 'main.o' failed
make: *** [main.o] Error 1
It seems that something not supported in qt 4.8.7 and I should take this into account and change my code. But I don't know what change.
Thank you in advance.
I have fixed my issue.
A have added move constructor TChannel struct:
TChannel(TChannel&& that)
{
_title = std::move(that._title);
}
It helped because move constructor was introduced in Qt 5.2.

serializing union type via custom function: "static assertion failed:: typex::value"

I am serializing the cl_long2 type from OpenCL which is defined like this (simplified from /usr/include/CL/cl_platform.hpp):
typedef int64_t cl_long;
typedef union
{
cl_long __attribute__ ((aligned(16))) s[2];
struct{ cl_long x, y; };
struct{ cl_long s0, s1; };
struct{ cl_long lo, hi; };
} cl_long2;
I defined the following stand-alone serialization function:
namespace boost{ namespace serialization {
template<class Archive> void serialize(Archive &ar, cl_long2 &i, const unsigned version){
ar & make_nvp("x",i.x);
ar & make_nvp("y",i.y);
}
}};
When I compile my code, which invokes a serialization of cl_long2 from as a class member, I am getting the following error, which I cannot understand (the error is the same if it is not a std::vector<cl_long2>, just a stand-alone variable):
/usr/include/boost/archive/detail/check.hpp: In function ‘void boost::archive::detail::check_object_level() [with T = cl_long2]’:
/usr/include/boost/archive/detail/iserializer.hpp:438:9: instantiated from ‘static void boost::archive::detail::load_non_pointer_type<Archive>::invoke(Archive&, T&) [with T = cl_long2, Archive = boost::archive::xml_iarchive]’
/usr/include/boost/archive/detail/iserializer.hpp:592:5: instantiated from ‘void boost::archive::load(Archive&, T&) [with Archive = boost::archive::xml_iarchive, T = cl_long2]’
/usr/include/boost/archive/detail/common_iarchive.hpp:66:9: instantiated from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&, int) [with T = cl_long2, Archive = boost::archive::xml_iarchive]’
/usr/include/boost/archive/basic_xml_iarchive.hpp:86:9: instantiated from ‘void boost::archive::basic_xml_iarchive<Archive>::load_override(const boost::serialization::nvp<T>&, int) [with T = cl_long2, Archive = boost::archive::xml_iarchive]’
/usr/include/boost/archive/xml_iarchive.hpp:93:9: instantiated from ‘void boost::archive::xml_iarchive_impl<Archive>::load_override(T&, int) [with T = const boost::serialization::nvp<cl_long2>, Archive = boost::archive::xml_iarchive]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:60:9: [ skipping 5 instantiation contexts ]
/usr/include/boost/serialization/split_free.hpp:58:9: instantiated from ‘static void boost::serialization::free_loader<Archive, T>::invoke(Archive&, T&, unsigned int) [with Archive = boost::archive::xml_iarchive, T = std::vector<cl_long2>]’
/usr/include/boost/serialization/split_free.hpp:74:5: instantiated from ‘void boost::serialization::split_free(Archive&, T&, unsigned int) [with Archive = boost::archive::xml_iarchive, T = std::vector<cl_long2>]’
/usr/include/boost/serialization/vector.hpp:151:5: instantiated from ‘void boost::serialization::serialize(Archive&, std::vector<U, Allocator>&, unsigned int) [with Archive = boost::archive::xml_iarchive, U = cl_long2, Allocator = std::allocator<cl_long2>]’
/usr/include/boost/serialization/serialization.hpp:128:9: instantiated from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::xml_iarchive, T = std::vector<cl_long2>]’
/usr/include/boost/archive/detail/iserializer.hpp:188:5: instantiated from ‘void boost::archive::detail::iserializer<Archive, T>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const [with Archive = boost::archive::xml_iarchive, T = std::vector<cl_long2>]’
myFile.cpp:368:2: instantiated from here
/usr/include/boost/archive/detail/check.hpp:60:5: error: static assertion failed: "typex::value"
The same error appears regardless of whether the archive type is xml or binary. I am using boost::serialization 1.46.
Any hints?
**EDIT: A smaller example including error is at http://ideone.com/4UgCn
If you look at the line where the assertion fails (detail/check.hpp:60), there is a comment right above it:
// trap attempts to serialize objects marked
// not_serializable
BOOST_STATIC_ASSERT(typex::value);
The documentation of this 'not_serializable' trait says that you have to enable this long2 type first. As you found out, this is done by:
BOOST_CLASS_IMPLEMENTATION(long2,boost::serialization::object_serializable)

Resources