af::array 转换为 float 或 double
af::array conversion to float or double
我一直在试验 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
函数,它有不同的形式:sf::sum(af::array)
,returns 设备内存中的 af::array
和模板化的 af::sum<T>(af::array)
那 returns 主机内存中的一个 T
。因此,对您的示例的最小更改是使用 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::mean
函数用于计算 af::array
的平均值。
- 一般来说,
RcppArrayFire::typed_array<T>
只需要将数组从 R 转换为 C++。在 C++ 中以及返回的方式中,您可以使用 af::array
.
- 即使您的设备不支持
double
,您仍然可以在主机上使用 double
值。
- 为了获得良好的性能,您应该避免
for
循环并使用 vectorized functions,就像在 R 中一样。您必须为 X
和 [=28 施加相同的维度=],虽然。
有趣的是,当我使用向量化函数时,我得到了不同的结果。现在我不确定为什么会这样,但下面的表格对我来说更有意义。您应该验证结果是否是您想要得到的:
#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);
}
一般来说,尽可能多地使用内置函数是个好主意。
我一直在试验 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
函数,它有不同的形式:sf::sum(af::array)
,returns 设备内存中的 af::array
和模板化的 af::sum<T>(af::array)
那 returns 主机内存中的一个 T
。因此,对您的示例的最小更改是使用 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::mean
函数用于计算af::array
的平均值。 - 一般来说,
RcppArrayFire::typed_array<T>
只需要将数组从 R 转换为 C++。在 C++ 中以及返回的方式中,您可以使用af::array
. - 即使您的设备不支持
double
,您仍然可以在主机上使用double
值。 - 为了获得良好的性能,您应该避免
for
循环并使用 vectorized functions,就像在 R 中一样。您必须为X
和 [=28 施加相同的维度=],虽然。
有趣的是,当我使用向量化函数时,我得到了不同的结果。现在我不确定为什么会这样,但下面的表格对我来说更有意义。您应该验证结果是否是您想要得到的:
#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);
}
一般来说,尽可能多地使用内置函数是个好主意。