c++ - 对工作程序中自定义函数的 undefined reference (C++ 和 RcppParallel)

标签 c++ r rcpp rcppparallel

我是 C++ 编程的新手,正在尝试通过 R 试验 Rcpp。 我创建了一个函数来从一个字符串中生成所有可能的 k-mers。它以它的串行形式运行良好:

#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;
}

但是,当我尝试在并行实现(使用 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;
}

编译失败,给出一个:undefined reference to p_cpp_kmer::cpp_kmer(std::string, int)'错误。

我知道它与声明/引用 cpp_kmer 有关,但我不知道在哪里/如何适本地这样做(由于我缺乏 C++ 知识)。

非常感谢您。

最佳答案

发生的情况是您的 p_cpp_kmer 结构声明了一个 cpp_kmer 方法,但它从未被定义。相反,稍后定义的是自由函数 cpp_kmer

你声明这个方法

std::vector< std::string > cpp_kmer( std::string s, int k );

你似乎想使用它:

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);
}

但是您在这里定义了自由函数 cpp_kmer:

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;
}

您可以删除结构中 cpp_kmer 方法的定义以便使用自由函数,或者实际定义它。

代码还有其他问题:

  • 在您的 operator() 中,您丢弃了结果。我猜你的意思是用这个代替 output[i] = cpp_kmer(sub_s, k);

  • 即使您执行上述代码也是不安全的,因为 output[i] = cpp_kmer(sub_s, k); 分配 R 对象(每个单独的 R 字符串和字符串vector) ,这不能在单独的线程中发生。

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

此外,当您考虑使用 C++11 和底层 RcppParallel 的 tbb 库时,编写并行代码会容易得多。例如:

#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 ;
}

这是假设 std::string 可以在单独的线程中分配:

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

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

关于c++ - 对工作程序中自定义函数的 undefined reference (C++ 和 RcppParallel),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43511683/

相关文章:

rcpp - 使用 RcppArmadillo 时无法使用 devtools 构建 R 包

c++ - RcppArmadillo ifft2 与 R 的原生 mvfft

c++ - 从 C 数组初始化 std::array 的正确方法

c++ - 用 C 重写 C++ 类

r - 遍历 df,grep,然后拆分

r - 如何将此 'for' 循环转换为向量解

通过 RCpp 返回 NA

c++ - 状态机与开关盒

c++ - 从具有成员函数的共享指针的 std::vector 中移除_if

r - 具有正态曲线的 Ggpairs barDiag