R并行写入SEXP结构
R parallel write SEXP structure
我正在使用C/C++代码开发R中的数据处理模块,主要是出于速度原因。这是我问题的事实清单。
- 最终结果数据是字符串向量的列表,占用20MB到200MB的内存
- 数据处理可以适用于单生产者/多消费者模型
- 对于我的数据,
wrap
将vector<vector<string> >
转换为List
需要相当长的时间
因此,我打算直接在SEXP结构中工作,这样我就可以节省最终转换的时间。我的主要功能是这样的。
boost::atomic<bool> done(false);
SEXP myfun(...) {
...
SEXP sdataStr;
PROTECT(sdataStr=allocVector(VECSXP, nElem));
vector<SEXP> dataStr(nElem);
for (int i=0; i<nElem; ++i) {
dataStr[i]=SET_VECTOR_ELT(sdataStr, i, allocVector(STRSXP, n));
}
Producer producer(&queue);
Consumer consumer1(dataStr, nElem, &queue);
Consumer consumer2(dataStr, nElem, &queue);
boost::thread produce(producer);
boost::thread consume1(consumer1);
boost::thread consume2(consumer2);
produce.join();
done=true;
consume1.join();
consume2.join();
UNPROTECT(1);
return sdataStr;
}
我的消费者类看起来像这个
class Consumer {
vector<SEXP>& m_dataStr;
boost::lockfree::queue<buffer>* m_queue;
buffer m_buffer;
public:
Consumer(vector<SEXP>& dataStr, boost::lockfree::queue<buffer>* queue) : m_dataStr(dataStr), m_queue(queue) {}
void operator()() {
while (!done) {
while (m_queue->pop(m_buffer)) {
process_item();
}
}
while (m_queue->pop(m_buffer)) {
process_item();
}
}
private:
process_item() {
...
// for some 0<=idx<nElem, 0<=i<n, some char* f and integer len
SET_STRING_ELT(m_dataStr[idx], i, mkCharLen(f,len));
...
}
}
这些是我唯一使用Rinternals的地方。程序的逻辑确保不同线程对同一位置的写入永远不会发生,即Consumer
类中的idx
和i
组合最多只能发生一次。我遇到了各种奇怪的问题,比如"堆栈不平衡",或者"进入错误的一代"等等。有什么我遗漏的吗?或者不建议在多个线程中调用SET_STRING_ELT?非常感谢!
C/R API函数不应在线程中调用,除非您知道自己在做什么,例如mkCharLen
可能会修改用于所有R字符串的内部哈希表,因此无法在线程中进行调用。SET_STRING_ELT
可能在线程中也不可用,尤其是在写屏障打开的情况下。
相关文章:
- 如何循环打印顶点结构
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 孤立代码块在结构中引发异常
- 有什么方法可以遍历结构吗
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 无法将结构注册为增强几何体3D点
- 多成员Constexpr结构初始化
- C++将文本文件中的数据读取到结构数组中
- 如何重构类层次结构以避免菱形问题
- 如何在C++中序列化结构数据
- std::vector的包装器,使数组的结构看起来像结构的数组
- 没有为自己的结构调用列表推回方法
- 奇怪的结构&GCC&clang(void*返回类型)
- 在 c++ 中拥有一组结构的正确方法是什么?
- vscode g++链路故障:体系结构x86_64的未定义符号
- R并行写入SEXP结构