简体   繁体   English

当算法放在循环内时,它会产生不同的结果,C++

[英]When algorithm is placed inside loop it produces different results, C++

I create the following algorithm in Rcpp and compile it in R.我在 Rcpp 中创建以下算法并在 R 中编译它。

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadilloExtensions/sample.h>

// [[Rcpp::export]]

arma::colvec Demo(arma::mat n, int K){
  
  arma::colvec N(K);
  
  for(int j=0; j<K; ++j){
    for(int i=0; i<(K-j); ++i){
      N[j] += accu(n.submat(i,0,i,j));
    }
  } 
  return N;
}

/***R
K = 4
n = cbind(c(1008, 5112, 1026, 25, 0), 0, 0, 0, 0)
Demo(n,K)

for(i in 1:3){
 print(Demo(n,K))
 print(K)
 print(n)
}
*/

However, something really weird happens when I run it inside a loop.但是,当我在循环中运行它时,会发生一些非常奇怪的事情。

For example, if I have例如,如果我有

> K = 4
> n
     [,1] [,2] [,3] [,4] [,5]
[1,] 1008    0    0    0    0
[2,] 5112    0    0    0    0
[3,] 1026    0    0    0    0
[4,]   25    0    0    0    0
[5,]    0    0    0    0    0

Then if I run the algorithm Demo a single time I receive the correct result然后,如果我一次运行算法Demo ,我会收到正确的结果

> Demo(n,K)
     [,1]
[1,] 7171
[2,] 7146
[3,] 6120
[4,] 1008

However, if I run it multiple times inside a loop, it starts to behave weird但是,如果我在一个循环中多次运行它,它就会开始表现得很奇怪

for(i in 1:3){
 print(Demo(n,K))
 print(K)
 print(n)
}
    [,1]
[1,] 7171
[2,] 7146
[3,] 6120
[4,] 1008
[1] 4
     [,1] [,2] [,3] [,4] [,5]
[1,] 1008    0    0    0    0
[2,] 5112    0    0    0    0
[3,] 1026    0    0    0    0
[4,]   25    0    0    0    0
[5,]    0    0    0    0    0
      [,1]
[1,] 14342
[2,] 14292
[3,] 12240
[4,]  2016
[1] 4
     [,1] [,2] [,3] [,4] [,5]
[1,] 1008    0    0    0    0
[2,] 5112    0    0    0    0
[3,] 1026    0    0    0    0
[4,]   25    0    0    0    0
[5,]    0    0    0    0    0
      [,1]
[1,] 21513
[2,] 21438
[3,] 18360
[4,]  3024
[1] 4
     [,1] [,2] [,3] [,4] [,5]
[1,] 1008    0    0    0    0
[2,] 5112    0    0    0    0
[3,] 1026    0    0    0    0
[4,]   25    0    0    0    0
[5,]    0    0    0    0    0

In the first run, it computes it correctly, then in the second run it gives the correct output multiplied by 2, and in the third run, it gives the correct output multiplied by 3. But based on the algorithm steps, I do not see an obvious step that produces this kind of behavior.在第一次运行中,它计算正确,然后在第二次运行中给出正确的 output 乘以 2,在第三次运行中,它给出正确的 output 乘以 3。但根据算法步骤,我没有看到产生这种行为的明显步骤。

The correct output should have been正确的 output 应该是

for(i in 1:3){
 print(Demo(n,K))
}
     [,1]
[1,] 7171
[2,] 7146
[3,] 6120
[4,] 1008
     [,1]
[1,] 7171
[2,] 7146
[3,] 6120
[4,] 1008
     [,1]
[1,] 7171
[2,] 7146
[3,] 6120
[4,] 1008

You are incrementing N in place via += .您正在通过+=增加N

Your function fails to ensure it is initialized at zero.您的 function 无法确保将其初始化为零。 Rcpp tends to do that by default (as I think it is prudent) -- but this can be suppressed for speed if you know you are doing.默认情况下, Rcpp倾向于这样做(因为我认为这是谨慎的)——但如果你知道你正在这样做,这可以被抑制以提高速度。

A minimally repaired version of your code (with the correct header, and a call to .fill(0) ) follows.代码的最低修复版本(使用正确的 header,并调用.fill(0) )如下。

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>

// [[Rcpp::export]]
arma::colvec Demo(arma::mat n, int K){
    arma::colvec N(K);
    N.fill(0);   // important, or construct as N(k, arma::fill::zeros)
    for(int j=0; j<K; ++j){
        for(int i=0; i<(K-j); ++i){
            N[j] += accu(n.submat(i,0,i,j));
        }
    }
    return N;
}

/***R
K = 4
n = cbind(c(1008, 5112, 1026, 25, 0), 0, 0, 0, 0)
Demo(n,K)

for(i in 1:3) {
 print(Demo(n,K))
 print(K)
 print(n)
}
*/

You could also call .zeros() (once constructed) or use zeros(k) (to construct) or... deploy a number of different ways to ensure your content is cleared before adding to it.您还可以调用.zeros() (一旦构造)或使用zeros(k) (构造)或...部署多种不同的方法来确保在添加内容之前清除您的内容。

The shortest, after checking the documentation, may be arma::colvec(N, arma::fill::zeros) .检查文档后,最短的可能是arma::colvec(N, arma::fill::zeros)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM