Почему Rcout и Rprintf вызывают ошибку ограничения стека при многопоточности? - PullRequest
0 голосов
/ 30 апреля 2018

Таким образом, в следующем коде, который я использую std::thread() для сообщения о ходе выполнения программы, пример был изменен, чтобы сообщать с неоправданным интервалом с неинформативным сообщением, чтобы продемонстрировать проблему.

#include <Rcpp.h>
#include <thread>
#include <chrono>
#include <atomic>
using namespace Rcpp;

void reporter(const std::atomic<bool> &running) {
    while (running) {
        Rprintf( "Program running...\n" );
        std::this_thread::sleep_for(std::chrono::microseconds(10));
    }
}

// [[Rcpp::export]]
void example() {
    int i = 1;
    std::atomic<bool> running{true};

    std::thread reporter_thread(
        [&] () { reporter(running); }
    );

    while (true) {
        i++;
        i--;
    }


    return;
}

На моем MacBook Pro 2017 года это вызывает сбой stack usage is too close to the limit на 93-м отпечатке. Это также дает сбой, если я перейду на Rprintf, однако, насколько я могу судить, std::cout неуязвим.

Я могу изменить код так, чтобы печать происходила в родительском потоке с флагом, который переключается в порожденном потоке, что также, по-видимому, позволяет избежать сбоя.

#include <Rcpp.h>
#include <thread>
#include <chrono>
#include <atomic>
using namespace Rcpp;

void reporter(const std::atomic<bool> &running, std::atomic<bool> &print_message) {
    while (running) {
        std::this_thread::sleep_for(std::chrono::microseconds(10));
        print_message = true;
    }
}

// [[Rcpp::export]]
void example() {
    int i = 1;
    std::atomic<bool> running{true};
    std::atomic<bool> print_message{true};

    std::thread reporter_thread(
        [&] () { reporter(running, print_message); }
    );

    while (true) {
        i++;
        i--;
        if (print_message)
            Rprintf( "Program running...\n" );
            print_message = false;
    }


    return;
}

Итак, у меня два вопроса:

  1. Почему первая версия вызывает сбой.
  2. Вторая версия гарантированно безопасна?

1 Ответ

0 голосов
/ 30 апреля 2018

Относительно вашего первого примера Написание расширений R должно сказать:

Вызов любого из API R из многопоточного кода «только для экспертов»: им нужно будет прочитать исходный код, чтобы определить, является ли он потокобезопасным. В частности, код, использующий механизм проверки стека, не должен вызываться из многопоточного кода.

Я бы держался подальше от вызова функций R API в многопоточном коде. Я не уверен в вашем втором примере, но сначала буду искать существующие решения, например, http://gallery.rcpp.org/articles/using-rcppprogress/.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...