c++ - 使非 const 对象成员函数在 openMP 中可用
问题描述
我想并行化一些循环,并在代码的其他部分广泛使用 openMP。我想在循环中使用一个对象,该对象具有一些后备存储(应该跨线程共享)和一些状态(应该是每个线程私有的)。
想象一下:
class P {
public:
// fills storage with 0, 1, 2...
P(size_t something) {
for(size_t i = 0; i < something; i++)
m_storage.push_back(i);
}
// finds the closest value in m_storage to probe
// the algorithm is a stupid dummy, but gets the point across
float findClosest(float probe) {
m_state = std::numeric_limits<float>::max();
auto closest = std::numeric_limits<float>::quiet_NaN();
for(const auto x: m_storage)
if(m_state > probe - x) {
closest = x;
m_state = probe - x;
}
return closest;
}
private:
std::vector<float> m_storage;
float m_state;
}
// sequential access
int main(){
P p = new P(100);
std::vector<float> results(5);
for(size_t i = 0; i<5; i++) {
results[i] = p.findClosest(i);
}
}
// parallel access with copy => p.m_storage is copied
int main(){
P p = new P(100);
std::vector<float> results(5);
#pragma omp parallel for firstprivate(p)
for(size_t i = 0; i<5; i++) {
results[i] = p.findClosest(i);
}
}
// parallel access with share => p.m_state is altered by multiple threads
int main(){
P p = new P(100);
std::vector<float> results(5);
#pragma omp parallel for firstprivate(p)
for(size_t i = 0; i<5; i++) {
results[i] = p.findClosest(i);
}
}
所以要么我浪费了大量的内存和缓存空间,要么实现因为变量的共享使用而中断。
我想我不能将对象的某些部分标记为共享的,而其他部分则标记为私有的或类似的东西。对象相当复杂,状态在不同的地方使用。有什么神奇的方法可以让对象共享它的存储,但每个对象都有状态吗?
例如类似的东西
[...]
private:
#pragma omp parallel shared
std::vector<float> m_storage;
#pragma omp parallel private
float m_state;
解决方案
将您的数据分为两类:一类保存要在线程之间共享的所有数据,另一类保存每个线程的私有数据。per-thread 类将保存一个const
指向公共数据的指针或引用(const
因为您不想对其进行更改)。
就像是:
class common {
public:
std::vector<float> m_storage;
// ...
};
class private_data {
public:
private_data(const common *cstorage): storage(cstorage) { }
const common *storage;
float findClosest(float probe) {
// ...
}
};
该类common
将有一个实例,传递给所有private_data
类。
推荐阅读
- node.js - JSON.stringify() 没有正确地将对象转换为字符串
- python - 如何更新窗口上的所有画布项目(因此,画布)调整大小?
- beacon - 如何更改我自己的 esp32-beacon 上的 TX 电源?
- asp.net - 强制 UpdatePanel 从母版页重新加载
- go - 依赖注入:函数集合的模式和命名
- r - 如何使用 2 个带和不带黑色填充的形状为 2 x 2 实验处理设计制作 ggplot2 散点图图例
- c# - 无法构建 .Net core 2.2 项目?找不到类型或命名空间名称“系统”
- sockets - 为什么我们使用无限循环让套接字服务器保持监听?
- r - 无法在 RStudio 中使用 blogdown 服务站点()
- java - 如何将 char 从 0-1 转换为 double?