Доступ к началу и концу в RcppParallel (exmaple вычисляет среднее значение вектора)

#c #r #rcpp #rcppparallel

#c #r #rcpp #rcppparallel

Вопрос:

У меня возникла проблема при попытке изучить RcppParallel. Я попытался изменить форму кода https://rcppcore.github.io/RcppParallel / для векторного суммирования вместо этого вычислить среднее значение вектора, чтобы посмотреть, понимаю ли я общий принцип.

Мой код показан ниже. Использование функции parallelVectorMean() на c (1,2,3,4,5) дает противоречивые и чаще всего неправильные результаты. Я предполагаю, что это связано с тем, что я не понимаю, как правильно обращаться к началу и концу, чтобы соответственно масштабировать мои частичные средние значения во время объединения.

 // [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>
#include <Rcpp.h>
using namespace RcppParallel;

struct Mean : public Worker
{
   // source vector
   const RVector<double> input;
   
   // accumulated value
   double value;
   
   // number of elements
   double num;
   
   // constructors
   Mean(const Rcpp::NumericVector input) : input(input), value(0), num(0) {}
   Mean(const Meanamp; mean, Split) : input(mean.input), value(0), num(0) {}
   
   // accumulate just the element of the range I've been asked to
   void operator()(std::size_t begin, std::size_t end) {
      num = (double) end - (double) begin;
      value  = (std::accumulate(input.begin()   begin, input.begin()   end, 0.0) / num);
   }
   
   // join my value with that of another Mean
   void join(const Meanamp; rhs) {
      value = (num*value   rhs.num*rhs.value)/(num   rhs.num);
      num = num   rhs.num;
   }
};

// [[Rcpp::export]]
double parallelVectorMean(Rcpp::NumericVector x) {
   
   // declare the MeanBody instance
   Mean mean(x);
   
   // call parallel_reduce to start the work
   RcppParallel::parallelReduce(0, x.length(), mean);
   
   // return the computed mean
   return mean.value;
}
  

Я с нетерпением жду возможности поучиться у вас, ребята.

Ответ №1:

Доступ к началу и концу — это нормально, но логика вашей операторной функции неверна.

Проверьте это:

    void operator()(std::size_t begin, std::size_t end) {
      double temp_num = (double) end - (double) begin;
      double temp_value = (std::accumulate(input.begin()   begin, input.begin()   end, 0.0) / temp_num);
      value = (num*value   temp_num*temp_value)/(num   temp_num);
      num = num   temp_num;
   }
  

Поток может продолжить работу в новом диапазоне без объединения, поэтому вы должны учитывать эту возможность.