多线程时为什么Rcout和Rprintf会出现stack limit error?
Why does Rcout and Rprintf cause stack limit error when multithreading?
所以在下面的代码中,我使用 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;
}
在我的 2017 款 MacBook Pro 上,这恰好在第 93 次打印时触发了 stack usage is too close to the limit
崩溃。如果我更改为 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;
}
所以我有两个问题:
- 为什么第一个版本会导致崩溃。
- 第二个版本能保证安全吗?
关于你的第一个例子 Writing R Extensions 不得不说:
Calling any of the R API from threaded code is ‘for experts only’: they will need to read the source code to determine if it is thread-safe. In particular, code which makes use of the stack-checking mechanism must not be called from threaded code.
我会远离在线程代码中调用 R API 函数。我不确定你的第二个例子,但会先寻找现有的解决方案,例如http://gallery.rcpp.org/articles/using-rcppprogress/。
所以在下面的代码中,我使用 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;
}
在我的 2017 款 MacBook Pro 上,这恰好在第 93 次打印时触发了 stack usage is too close to the limit
崩溃。如果我更改为 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;
}
所以我有两个问题:
- 为什么第一个版本会导致崩溃。
- 第二个版本能保证安全吗?
关于你的第一个例子 Writing R Extensions 不得不说:
Calling any of the R API from threaded code is ‘for experts only’: they will need to read the source code to determine if it is thread-safe. In particular, code which makes use of the stack-checking mechanism must not be called from threaded code.
我会远离在线程代码中调用 R API 函数。我不确定你的第二个例子,但会先寻找现有的解决方案,例如http://gallery.rcpp.org/articles/using-rcppprogress/。