我第一次尝试了Rcpp功能inline,它解决了我的速度问题(感谢Dirk!):
R:将负值替换为零
初始版本看起来像这样:
library(inline)
cpp_if_src <- '
Rcpp::NumericVector xa(a);
int n_xa = xa.size();
for(int i=0; i < n_xa; i++) {
if(xa[i]<0) xa[i] = 0;
}
return xa;
'
cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")
Run Code Online (Sandbox Code Playgroud)
但是当被调用时cpp_if(p),它会p用输出覆盖,这不是预期的.所以我认为它是通过引用传递的.
所以我用以下版本修复它:
library(inline)
cpp_if_src <- '
Rcpp::NumericVector xa(a);
int n_xa = xa.size();
Rcpp::NumericVector xr(a);
for(int i=0; i < n_xa; i++) {
if(xr[i]<0) xr[i] = 0;
}
return xr;
'
cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")
Run Code Online (Sandbox Code Playgroud)
这似乎有效.但是现在,当我将其重新加载到R中时,原始版本不再覆盖其输入(即,相同的确切代码现在不会覆盖其输入):
> cpp_if_src <- '
+ Rcpp::NumericVector …Run Code Online (Sandbox Code Playgroud) 我刚刚用Rcpp编写了一个新版本的ABCoptim包.大约30倍的加速,我对新版本的性能(与旧版本)非常满意,但我仍然有一些担心,如果我有空间来提高性能而不需要修改太多的代码.
在ABCoptim的主要功能(用C++编写)中,我传递一个包含"蜜蜂位置"(NumericMatrix)的Rcpp :: List对象和一些带有算法本身重要信息的NumericVectors.我的问题是,当我将Rcpp :: List对象传递给其他函数时,例如
#include <Rcpp.h>
using namespace Rcpp;
List ABCinit([some input]){[some code here]};
void ABCfun2(List x){[some code here]};
void ABCfun3(List x){[some code here]};
List ABCmain([some input])
{
List x = ABCinit([some input]);
while ([some statement])
{
ABCfun2(x);
ABCfun3(x);
}
...
return List::create(x["results"]);
}
Run Code Online (Sandbox Code Playgroud)
Rcpp在while循环中做了什么?请问x对象是通过引用或深拷贝的功能传递ABCfun2和ABCfun3?我已经看到'const List&x'的用法,它告诉我可以使用指针传递Rcpp对象,但问题是我需要这个列表是可变的(并且没有常量),无论如何要改进它吗?我担心这个x List的迭代拷贝可能会减慢我的代码速度.
PS:我还是C++的新手,而且我正在使用Rcpp来学习C++.
看看rcpp文档和Rcpp::DataFrame库中我意识到我不知道如何通过引用修改DataFrame.谷歌搜索了一下我在SO上找到了这篇文章,这篇文章在档案上.没有什么明显的,所以我怀疑我会错过一些像"已经是这种情况因为"或"因为它没有意义"的大事.
我尝试了以下编译,但data.frame传递给updateDFByRefR 的对象 保持不变
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void updateDFByRef(DataFrame& df) {
int N = df.nrows();
NumericVector newCol(N,1.);
df["newCol"] = newCol;
return;
}
Run Code Online (Sandbox Code Playgroud) 我想将一个大矩阵传递给一个RcppArmadillo函数(大约30,000*30,000)并且感觉这个过去只会消耗所有的性能提升.这里还提出了一个问题,建议使用带有copy_aux_mem = false参数的高级构造函数.这似乎也是一个很好的解决方案,因为我只需要从矩阵中读取行而不需要改变任何东西.我在正确实施解决方案时遇到问题.这可能只是一个简单的语法问题.
这是我当前设置的函数调用(当然简化):
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::vec test(arma::mat M) {
return(M.row(0))
}
Run Code Online (Sandbox Code Playgroud)
这是非常慢的大矩阵M(例如M=matrix(rnorm(30000*30000), nrow=30000, ncol=30000),所以我想使用这里记录的高级构造函数.语法是mat(aux_mem*, n_rows, n_cols, copy_aux_mem = true, strict = true)并且copy_aux_mem应该设置false为'传递引用'.我只是不确定语法功能定义.我该如何使用它arma::vec test(arma::mat M) {?
我正在尝试编写一个函数来计算字符串向量中唯一项的数量(我的问题稍微复杂一点,但这是可重现的.我根据我在C++中找到的答案做了这个.这是我的代码:
C++
int unique_sort(vector<string> x) {
sort(x.begin(), x.end());
return unique(x.begin(), x.end()) - x.begin();
}
int unique_set(vector<string> x) {
unordered_set<string> tab(x.begin(), x.end());
return tab.size();
}
Run Code Online (Sandbox Code Playgroud)
R:
x <- paste0("x", sample(1:1e5, 1e7, replace=T))
microbenchmark(length(unique(x)),unique_sort(x), unique_set(x), times=3)
Run Code Online (Sandbox Code Playgroud)
结果:
Unit: milliseconds
expr min lq mean median uq
length(unique(x)) 365.0213 373.4018 406.0209 381.7823 426.5206
unique_sort(x) 10732.1918 10847.0532 10907.6882 10961.9146 10995.4363
unique_set(x) 1948.6517 2230.3383 2334.4040 2512.0249 2527.2802
Run Code Online (Sandbox Code Playgroud)
查看该unique函数的R源代码(它有点难以理解),它似乎在数组上使用循环向哈希添加唯一元素,并检查该哈希是否已存在元素.
因此,我认为它应该等同于unordered_set方法.我不明白为什么unordered_set方法慢了5倍.
TLDR:为什么我的C++代码变慢?
以我的理解,在Rcpp和C ++之间转换向量将创建新向量,如下所示。我的理解正确吗?
将Rcpp向量转换为C ++向量时,我们使用Rcpp::as<T>()(例如Rcpp::as<std::string>用于Rcpp::CharacterVector)。
std::vector<std::string>创建后,原始Rcpp元素将被复制到C ++向量中std::string。这意味着修改新创建的C ++矢量元素不会影响原始的Rcpp矢量元素。
将C ++向量转换为Rcpp向量时,我们使用Rcpp::wrap()。创建具有相应类型的Rcpp向量,并将C ++元素作为Rcpp对象复制到Rcpp向量中。这意味着修改新创建的Rcpp矢量元素不会影响原始的C ++矢量元素。
我想在rcpp中更改ListMatrix列表的元素,但始终无法做到这一点.请参阅以下玩具示例:
library("Rcpp")
cppFunction('
ListMatrix ListMatrixType(ListMatrix x){
NumericMatrix a = x(0,0);
a(0,0) = 100;
return x;
}
')
x = matrix(list(matrix(0,3,2)),2,2)
a = ListMatrixType(x)
a[[1,1]]
a[[2,2]]
Run Code Online (Sandbox Code Playgroud)
我希望只会a[[1,1]改变,但为什么a[[2,2]]也会改变?
> a[[1,1]]
[,1] [,2]
[1,] 100 0
[2,] 0 0
[3,] 0 0
> a[[2,2]]
[,1] [,2]
[1,] 100 0
[2,] 0 0
[3,] 0 0
Run Code Online (Sandbox Code Playgroud)
我必须误解rcpp中的索引规则.所以我的问题是如何正确更改每个列表的元素?我想每个列表都包含一个矩阵.