af::数组转换为浮点数或双精度数



我一直在尝试RcppArrayFire软件包,主要是重写RcppArmadillo的一些成本函数,似乎无法克服"没有从'af::array'到'float'的可行转换。 我也遇到了一些后端错误,下面的示例似乎没有这些错误。

这个 cov-var 示例写得很差,只是为了使用我实际成本函数中的所有相关编码片段。 截至目前,它是"RcppArrayFire.package.skeleton"生成的软件包中唯一的添加物。

#include "RcppArrayFire.h"
#include <Rcpp.h>
// [[Rcpp::depends(RcppArrayFire)]]
// [[Rcpp::export]]
float example_ols(const RcppArrayFire::typed_array<f32>& X_vect,  const RcppArrayFire::typed_array<f32>& Y_vect){
int Len = X_vect.dims()[0];
int Len_Y = Y_vect.dims()[0];
while( Len_Y < Len){
Len --;
}
float mean_X = af::sum(X_vect)/Len;
float mean_Y = af::sum(Y_vect)/Len;
RcppArrayFire::typed_array<f32> temp(Len);
RcppArrayFire::typed_array<f32> temp_x(Len);
for( int f = 0; f < Len; f++){
temp(f) = (X_vect(f) - mean_X)*(Y_vect(f) - mean_Y);
temp_x(f) = af::pow(X_vect(f) -mean_X, 2);
}
return af::sum(temp)/af::sum(temp_x);
}

/*** R
X <- 1:10
Y <- 2*X +rnorm(10, mean = 0, sd = 1)
example_ols(X, Y)
*/

首先要考虑的是af::sum函数,它有不同的形式:一个在设备内存中返回af::arraysf::sum(af::array)和一个在主机内存中返回T的模板化af::sum<T>(af::array)。因此,对示例的最小更改是使用af::sum<float>

#include "RcppArrayFire.h"
#include <Rcpp.h>
// [[Rcpp::depends(RcppArrayFire)]]
// [[Rcpp::export]]
float example_ols(const RcppArrayFire::typed_array<f32>& X_vect,
const RcppArrayFire::typed_array<f32>& Y_vect){
int Len = X_vect.dims()[0];
int Len_Y = Y_vect.dims()[0];
while( Len_Y < Len){
Len --;
}
float mean_X = af::sum<float>(X_vect)/Len;
float mean_Y = af::sum<float>(Y_vect)/Len;
RcppArrayFire::typed_array<f32> temp(Len);
RcppArrayFire::typed_array<f32> temp_x(Len);
for( int f = 0; f < Len; f++){
temp(f) = (X_vect(f) - mean_X)*(Y_vect(f) - mean_Y);
temp_x(f) = af::pow(X_vect(f) -mean_X, 2);
}
return af::sum<float>(temp)/af::sum<float>(temp_x);
}

/*** R
set.seed(1)
X <- 1:10
Y <- 2*X +rnorm(10, mean = 0, sd = 1)
example_ols(X, Y)
*/

但是,还有更多可以改进的地方。排名不分先后:

  • 您不需要包含Rcpp.h
  • 有一个用于计算af::array平均值的af::mean函数。
  • 通常,只有将数组从 R 获取到 C++ 时才需要RcppArrayFire::typed_array<T>。在C++和返回的路上,您可以使用af::array.
  • 即使您的设备不支持double,您仍然可以在主机上使用double值。
  • 为了获得良好的性能,您应该避免for循环并使用矢量化函数,就像在 R 中一样。不过,你必须对XY施加相等的维度。

有趣的是,当我使用矢量化函数时,我得到了不同的结果。现在我不确定为什么会这样,但以下表格对我来说更有意义。您应该验证结果是否是您想要获得的结果:

#include <RcppArrayFire.h>
// [[Rcpp::depends(RcppArrayFire)]]
// [[Rcpp::export]]
double example_ols(const RcppArrayFire::typed_array<f32>& X_vect,
const RcppArrayFire::typed_array<f32>& Y_vect){
double mean_X = af::mean<double>(X_vect);
double mean_Y = af::mean<double>(Y_vect);
af::array temp = (X_vect - mean_X) * (Y_vect - mean_Y);
af::array temp_x = af::pow(X_vect - mean_X, 2.0);
return af::sum<double>(temp)/af::sum<double>(temp_x);
}
/*** R
set.seed(1)
X <- 1:10
Y <- 2*X +rnorm(10, mean = 0, sd = 1)
example_ols(X, Y)
*/ 

顺便说一句,更短的版本是:

#include <RcppArrayFire.h>
// [[Rcpp::depends(RcppArrayFire)]]
// [[Rcpp::export]]
af::array example_ols(const RcppArrayFire::typed_array<f32>& X_vect,
const RcppArrayFire::typed_array<f32>& Y_vect){
return af::cov(X_vect, Y_vect) / af::var(X_vect);
}

通常,尽可能多地使用内置函数是个好主意。

相关内容

  • 没有找到相关文章

最新更新