【发布时间】:2018-07-02 20:11:48
【问题描述】:
我正在尝试找到一种计算 X^T * W * X 的有效方法,其中 X 是一个密集的 mat 大小,例如10,000 x 10 并且 W 是对角矩阵(我只将对角线存储在 vec 中)。
目前,我使用这个功能
arma::mat& getXtW(const arma::mat& covar,
const arma::vec& w,
arma::mat& tcovar,
size_t n, size_t K) {
size_t i, k;
for (i = 0; i < n; i++) {
for (k = 0; k < K; k++) {
tcovar(k, i) = covar(i, k) * w(i);
}
}
return tcovar;
}
并计算
tcovar = getXtW(covar, w, tcovar, n, K);
cprod = tcovar * covar;
然而,这似乎不是最优的。
PS:你可以看到整个代码there。
Edit1:似乎我可以使用covar.t() * (covar.each_col() % w),但这似乎并没有快多少。
Edit2:如果我自己在 Rcpp 中使用循环实现它:
arma::mat testProdW2(const arma::mat& x, const arma::vec& w) {
int n = x.n_rows;
int K = x.n_cols;
arma::mat res(K, K);
double tmp;
for (int k = 0; k < K; k++) {
for (int j = k; j < K; j++) {
tmp = 0;
for (int i = 0; i < n; i++) {
tmp += x(i, j) * w[i] * x(i, k);
}
res(j, k) = tmp;
}
}
for (int k = 0; k < K; k++) {
for (int j = 0; j < k; j++) {
res(j, k) = res(k, j);
}
}
return res;
}
这比第一个实现要慢。
【问题讨论】:
-
过去,这是我的论文顾问等人使用的特殊函数类型。这可能仍然值得——通过跟踪索引,您可以跳过转置,并在移动时折叠
W。 -
@DirkEddelbuettel 不确定我理解。可以改一下吗?
-
想象一下手动编写一个矩阵 mult 例程。现在想象一下为矩阵及其转置做这件事。你可以优化。现在想象添加一个对角线权重向量。你仍然可以优化。
-
@DirkEddelbuettel 你会建议自己实现这个特定的产品(使用类似 3 个 for 循环)?
-
如果不是这个,请解释一下还有什么问题。
标签: performance rcpp armadillo