我是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;
}
无法编译,给出了:对p_cpp_kmer :: cpp_kmer(std :: string,int)&#39; 错误的未定义引用。
我知道它与声明/引用cpp_kmer有关,但我无法弄清楚在哪里/如何做到这一点(由于我缺乏C ++知识)。
非常感谢你。
答案 0 :(得分:2)
您的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字符串和字符串向量),这在单独的线程中不会发生。
如果您确实想要并行执行此操作,则需要确保不在工作程序中分配任何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"
答案 1 :(得分:0)
对于不同的结构(或公共名称空间),您可能有using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Configuration;
using System.IO;
using System.Collections;
using SAIT_Electronics.Models;
namespace SAIT_Electronics.Pages.Management
{
public partial class ManageProducts : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ImagesFolder();
//check if the url contains an id parameter
if (!string.IsNullOrWhiteSpace(Request.QueryString["id"]))
{
int id = Convert.ToInt32(Request.QueryString["id"]);
FillPage(id);
}
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
productmodel ProductModel = new productmodel();
Product product = CreateProduct();
//check if the url contains an id parameter
if (!string.IsNullOrWhiteSpace(Request.QueryString["id"]))
{
//id exist -> update existing row
int id = Convert.ToInt32(Request.QueryString["id"]);
lblResults.Text = ProductModel.UpdateProduct(id, product);
}
else
{
//id does not exist -> create a new row
lblResults.Text = ProductModel.InsertProduct(product);
}
}
private void FillPage(int id)
{
// get selected products from db
productmodel ProductModel = new productmodel();
Product product = ProductModel.GetProduct(id);
//fill text boxes
txtDescription.Text = product.Description;
txtName.Text = product.Name;
txtPrice.Text = product.Price.ToString();
//set dropdown list values
ddImage.SelectedValue = product.Image;
ddType.SelectedValue = product.TypeId.ToString();
}
private void ImagesFolder()
{
try
{
//get all file paths
//string[] images = Directroy.GetFiles(Server.MapPath("~/Images/Products/"));
// string[] images = Server.MapPath(@"/Images/Products/");
string[] images = System.IO.Directory.GetFiles(Server.MapPath("~/Images/Products/"));
// String images = new DirectoryInfo(@"D:\Desktop\Shoping\SAIT_Electronics\SAIT_Electronics\Images\Products\").Name;
//string[] images = Directory.GetFiles(("~/D:/Desktop/Shoping/SAIT_Electronics/SAIT_Electronics/Images/Products/"), "*.xml");
//get all file names and add them to an arraylist
ArrayList imageList = new ArrayList();
foreach (string image in images )
{
string imageName = image.Substring(image.LastIndexOf(@"\", StringComparison.Ordinal) + 1);
imageList.Add(imageName);
}
// set the array list as dropdwon views datasouce and refresh
ddImage.DataSource = imageList;
ddImage.AppendDataBoundItems = true;
ddImage.DataBind();
}
catch (Exception e)
{
lblResults.Text = e.ToString();
}
}
private Product CreateProduct()
{
Product product = new Product();
product.Name = txtName.Text;
product.Price = Decimal.Parse(txtPrice.Text);
product.TypeId = Convert.ToInt32(ddType.SelectedValue);
product.Description = txtDescription.Text;
product.Image = ddImage.SelectedValue;
return product;
}
}
}
的实现,但是在结构cpp_kmer
中缺少成员函数cpp_kmer
的实现。您必须添加如下实现:
p_cpp_kmer