辅助进程中自定义函数的未定义引用(C+;+;和RcppParallel) 我是C++编程新手,尝试通过R来实验Rcpp。 我创建了一个函数,从一个字符串生成所有可能的k-mers。它以It的系列形式运行良好: #include <Rcpp.h> #include <string> #include <iostream> #include <ctime> // using namespace Rcpp; // [[Rcpp::export]] std::vector< std::string > cpp_kmer( std::string s, int k ){ std::vector< std::string > kmers; int seq_loop_size = s.length() - k+1; for ( int z=0; z < seq_loop_size; z++ ) { std::string kmer; kmer = s.substr( z, k ); kmers.push_back( kmer ) ; } return kmers; } #包括 #包括 #包括 #包括 //使用名称空间Rcpp; //[[Rcpp::导出]] std::vectorcpp_kmer(std::string s,int k){ std::vectorkmers; int seq_loop_size=s.length()-k+1; 对于(int z=0;z

辅助进程中自定义函数的未定义引用(C+;+;和RcppParallel) 我是C++编程新手,尝试通过R来实验Rcpp。 我创建了一个函数,从一个字符串生成所有可能的k-mers。它以It的系列形式运行良好: #include <Rcpp.h> #include <string> #include <iostream> #include <ctime> // using namespace Rcpp; // [[Rcpp::export]] std::vector< std::string > cpp_kmer( std::string s, int k ){ std::vector< std::string > kmers; int seq_loop_size = s.length() - k+1; for ( int z=0; z < seq_loop_size; z++ ) { std::string kmer; kmer = s.substr( z, k ); kmers.push_back( kmer ) ; } return kmers; } #包括 #包括 #包括 #包括 //使用名称空间Rcpp; //[[Rcpp::导出]] std::vectorcpp_kmer(std::string s,int k){ std::vectorkmers; int seq_loop_size=s.length()-k+1; 对于(int z=0;z,c++,r,rcpp,rcppparallel,C++,R,Rcpp,Rcppparallel,但是,当我尝试在并行实现中使用此函数时(使用RcppParallel),代码如下: #include <Rcpp.h> #include <string> #include <iostream> #include <ctime> using namespace Rcpp; // [[Rcpp::depends(RcppParallel)]] #include <RcppParallel.h> using namespace RcppP

但是,当我尝试在并行实现中使用此函数时(使用RcppParallel),代码如下:

#include <Rcpp.h>
#include <string>
#include <iostream>
#include <ctime>
using namespace Rcpp;

// [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>
using namespace RcppParallel;

struct p_cpp_kmer : public Worker {
  // input string
  std::vector< std::string > seqs;
  int k;
  std::vector< std::string > cpp_kmer( std::string s, int k );
  // destination list
  List output;
  std::string
    sub_s;
  // initialize with source and destination
  p_cpp_kmer(std::vector< std::string > seqs, int k, List output) 
    : seqs(seqs), k(k), output(output) {}

  // calculate k-mers for the range of sequences requested
  void operator()(std::size_t begin, std::size_t end) {
    for (std::size_t i = begin; i < end; i++)
      sub_s = seqs[i];
      cpp_kmer(sub_s, k);
  }
};

// [[Rcpp::export]]
List par_cpp_kmer(std::vector< std::string > seqs, int k, bool v){
  // allocate output list 
  List outpar(num_seqs);
  int num_seqs = seqs.size();
  // p_cpp_kmer functor (pass input and output matrixes)
  p_cpp_kmer par_kmer(seqs, k, outpar);
  parallelFor(0, num_seqs, par_kmer);
  return wrap(outpar);
}

std::vector< std::string > cpp_kmer( std::string s, int k ){
  std::vector< std::string > kmers;
  int seq_loop_size = s.length() - k+1;
  for ( int z=0; z < seq_loop_size; z++ ) {
    std::string  kmer;
    kmer = s.substr( z, k );
    kmers.push_back( kmer ) ;
  }
  return kmers;
}
#包括
#包括
#包括
#包括
使用名称空间Rcpp;
//[[Rcpp::dependens(RcppParallel)]]
#包括
使用名称空间RcppParallel;
结构p_cpp_kmer:公共工作者{
//输入字符串
std::vectorseqs;
int k;
std::vectorcpp_kmer(std::string s,int k);
//目的地列表
列表输出;
字符串
副秘书长;
//使用源和目标初始化
p_cpp_kmer(std::vectorseqs,int k,列表输出)
:seqs(seqs),k(k),output(output){
//计算所需序列范围的k-mers
void运算符()(std::size\u t begin,std::size\u t end){
对于(std::size\u t i=begin;i序号,整数k,布尔值v){
//分配输出列表
列表输出(数量顺序);
int num_seqs=seqs.size();
//p_cpp_kmer函子(传递输入和输出矩阵)
p_cpp_kmer par_kmer(seqs,k,outpar);
parallelFor(0,num_seq,par_kmer);
返回包裹(outpar);
}
std::vectorcpp_kmer(std::string s,int k){
std::vectorkmers;
int seq_loop_size=s.length()-k+1;
对于(int z=0;z
它无法编译,给p_cpp_kmer::cpp_kmer(std::string,int)'error提供了一个:undefined引用

我知道这与声明/引用cpp_kmer有关,但我就是不知道在哪里/如何适当地这样做(因为我缺乏C++方面的知识)


非常感谢您。

您可能已经为不同的结构(或在公共命名空间中)实现了
cpp\u kmer
,但是您的结构
p\u cpp\u kmer
上缺少成员函数
cpp\u kmer
的实现。您必须添加以下实现:

std::vector< std::string > p_cpp_kmer::cpp_kmer( std::string s, int k ) {
  // your implementation goes here
}
std::vectorp_cpp_kmer::cpp_kmer(std::string s,int k){
//你的实现就在这里
}

发生的情况是,您的
p\u cpp\u kmer
结构声明了一个
cpp\u kmer
方法,但它从未定义过。相反,后面定义的是自由函数
cpp\u kmer

您声明了这个方法

std::vector< std::string > cpp_kmer( std::string s, int k );
您可以删除struct中
cpp\u kmer
方法的定义,以便使用free函数,也可以实际定义它

该代码还存在其他问题:

  • 操作符()
    中,放弃结果。我猜你的意思是让这个
    output[I]=cpp\u kmer(sub\u s,k)

  • 即使您执行类似于上述的操作,代码也是不安全的,因为
    output[i]=cpp\u kmer(sub\u s,k)分配R对象(每个单独的R字符串和字符串向量),这不能在单独的线程中发生

如果您真的想并行执行此操作,则需要确保在worker中不分配任何R对象

<> P>此外,在考虑使用C++ 11和TBB库的基础上,编写并行代码要容易得多,它的代码是<>代码> RCPPPalthix//Cuth>。例如:

#include <Rcpp.h>
#include <RcppParallel.h>

using namespace Rcpp;
using namespace RcppParallel;

// [[Rcpp::depends(RcppParallel)]]
// [[Rcpp::plugins(cpp11)]]

using string_vector = std::vector< std::string > ; 
using list_string_vector = std::vector<string_vector> ;

// [[Rcpp::export]]
list_string_vector par_cpp_kmer( string_vector  seqs, int k, bool v){
  int num_seqs = seqs.size() ;

  list_string_vector out(num_seqs) ;

  tbb::parallel_for( 0, num_seqs, 1, [&seqs,k,&out](int i){
    std::string& s = seqs[i] ;
    int seq_loop_size = s.length() - k+1;

    std::vector<std::string> vec(seq_loop_size) ;
    for ( int z=0; z < seq_loop_size; z++ ) {
      vec[z] = s.substr( z, k );
    }
    out[i] = vec ;

  }) ;
  return out ;
}

@StephanLechter,你的意思是将cpp_kmer的整个实现移动到p_cpp_kmer结构中吗?非常感谢,你的解决方案似乎非常简单,但是在尝试编译它时,我收到以下错误:
cpp_kmer_par_SO.cpp:10:7:错误:在“string_vector”cpp_kmer_par_SO之前应该有嵌套名称说明符。cpp:10:7:错误:“string_vector”尚未声明为cpp_kmer_par_SO.cpp:10:21:错误:应该是“;”在“=”标记之前
和类似于
列表\u字符串\u向量
声明的错误。我使用中的示例验证了我可以编译其他C++11代码。关于使代码“线程安全”,我尝试使用RVector方法,如前所述,但是我找不到任何将此结构与字符串而不是数字结合使用的示例。使用
预期嵌套名称说明符
时出现的错误表明您可能没有完整的C++11实现。也许你可以用一些
typedef
来代替。字符串不像
int
double
那么简单,所以如果你想使用
RVector
你必须非常小心,一旦你分配了一个,你就不安全了。简而言之,不要这样做。非常感谢您,我使用您的方法(在更新了C++的机器上)以及使用typedef在我的机器上编译并运行了它。我必须承认我没有获得多少速度优势,但我学到了教训。
std::vector< std::string > cpp_kmer( std::string s, int k ){
  std::vector< std::string > kmers;
  int seq_loop_size = s.length() - k+1;
  for ( int z=0; z < seq_loop_size; z++ ) {
    std::string  kmer;
    kmer = s.substr( z, k );
    kmers.push_back( kmer ) ;
  }
  return kmers;
}
#include <Rcpp.h>
#include <RcppParallel.h>

using namespace Rcpp;
using namespace RcppParallel;

// [[Rcpp::depends(RcppParallel)]]
// [[Rcpp::plugins(cpp11)]]

using string_vector = std::vector< std::string > ; 
using list_string_vector = std::vector<string_vector> ;

// [[Rcpp::export]]
list_string_vector par_cpp_kmer( string_vector  seqs, int k, bool v){
  int num_seqs = seqs.size() ;

  list_string_vector out(num_seqs) ;

  tbb::parallel_for( 0, num_seqs, 1, [&seqs,k,&out](int i){
    std::string& s = seqs[i] ;
    int seq_loop_size = s.length() - k+1;

    std::vector<std::string> vec(seq_loop_size) ;
    for ( int z=0; z < seq_loop_size; z++ ) {
      vec[z] = s.substr( z, k );
    }
    out[i] = vec ;

  }) ;
  return out ;
}
> par_cpp_kmer( c("foobar", "blabla"), 3 )
[[1]]
[1] "foo" "oob" "oba" "bar"

[[2]]
[1] "bla" "lab" "abl" "bla"