c++ - 如何避免文件变量成为 OpenMP 中的竞争条件(离散元方法模拟)
问题描述
我正在进行离散元法模拟,现在正在进行并行程序。到目前为止,我已经成功地在 4 个或更多核心上运行了代码,但我得到的数据显然都不正确。我发现问题是由于比赛条件而发生的。
我使用了一些文件范围向量(通过使用公共静态向量在类中声明)来恢复粒子相关信息(位置、速度、力)。而在我的接触检测类中,还涉及到其他类。
我的问题是,如何在没有竞争条件的情况下保护文件范围变量和对象?
这是我使用的方式和我的代码演示:在我声明静态变量后
添加,如下例所示threadprivate
Myclass{
public:
static <vector> ContactList;
static <vector> LeftMirrorVec;
static <vector> RightMirrorVec;
...
#pragma omp threadprivate(ContactList,LeftMirrorVec,RightMirrorVec)
而且这种方法导致内存存储不断累积,我不知道发生了什么。下面是我使用这些静态向量的部分main.cpp
#pragma omp parallel
{
int right;
int left;
int middle;
int SlaveCount;
double particleOverlap;
double tempXmaxParticles;
double tempXminParticles;
#pragma omp for schedule(dynamic,3) private(right,left,middle,SlaveCount,particleOverlap,tempXmaxParticles,tempXminParticles) reduction(+:KE)
for(int MasterCount=0; MasterCount<DataCollector::ParVec.size(); MasterCount++){
int ID = omp_get_thread_num();
//right zone detect
for(right=0; right<DataCollector::RightMirrorVec.size();right++){
if(DataCollector::ParVec[MasterCount].getParPosx()<Boundary::Xmax && DataCollector::ParVec[MasterCount].getParPosx()>Boundary::Xmax-DataCollector::ParVec[MasterCount].getParRadius()-DataCollector::RightMirrorVec[right].getParRadius()){
SlaveCount = DataCollector::RightMirrorVec[right].getparID(); //get the right mirror particle id
tempXmaxParticles = DataCollector::ParVec[SlaveCount].getParPosx(); //restore the original position
DataCollector::ParVec[SlaveCount].setParPosx(DataCollector::RightMirrorVec[right].getParPosx()); // move to the mirror pos
particleOverlap = DataCollector::ParVec[MasterCount].getParRadius()+DataCollector::ParVec[SlaveCount].getParRadius()-sqrt((DataCollector::ParVec[SlaveCount].getParPosx()-DataCollector::ParVec[MasterCount].getParPosx())*(DataCollector::ParVec[SlaveCount].getParPosx()-DataCollector::ParVec[MasterCount].getParPosx())+(DataCollector::ParVec[SlaveCount].getParPosy()-DataCollector::ParVec[MasterCount].getParPosy())*(DataCollector::ParVec[SlaveCount].getParPosy()-DataCollector::ParVec[MasterCount].getParPosy())); // overlap between real and right ghost particles
if(particleOverlap>0){
LSDmodel RightModel(time,input,MasterCount,SlaveCount,particleOverlap);
}
particleOverlap=0;
DataCollector::ParVec[SlaveCount].setParPosx(tempXmaxParticles);
LeftMirrorVecstatic vectors
和 RightMirrorVec 将被不同的线程重入以进行接触检测。
还有另一个问题,我在我的接触检测类中声明了一个对象,如下所示
LSDmodel::LSDmodel(TimeZone time,InputZone input, int MasterCount, int SlaveCount){
double DampTemp = -log(input.getRestituition())/pi;
DampRatio = DampTemp/sqrt(1+DampTemp*DampTemp);
if( MasterCount!=SlaveCount){
ContactParameter contactpara;
int ContactType =1;
double distx = DataCollector::ParVec[SlaveCount].getParPosx()-DataCollector::ParVec[MasterCount].getParPosx();
double disty = DataCollector::ParVec[SlaveCount].getParPosy()-DataCollector::ParVec[MasterCount].getParPosy();
double particleOverlap = DataCollector::ParVec[SlaveCount].getParRadius()+DataCollector::ParVec[MasterCount].getParRadius()-sqrt(distx*distx+disty*disty);
if(particleOverlap > 0){
static Material material(MasterCount,SlaveCount,ContactType);
#pragma omp threadprivate(material,contactpara)
contactpara.setUnitNormDir(MasterCount, SlaveCount);
...
如您所见,我在这里声明了来自不同类的两个不同构造函数。我进一步使用了他们的实例。
我的第二个问题是,构造函数是否会由不同的线程创建而不会相互影响contactpara
?
如果没有,请给我一些建议如何处理这些问题。如果需要更多详细信息,请告诉我,谢谢。material
解决方案
推荐阅读
- typescript - 输入类型如何选择输出并支持联合?
- python - 试图分散列表中单元格之间的差异
- speech-to-text - 哪些因素会导致声学模型失败?
- c++ - 在 C++ 中创建类型的类型列表组合
- google-cloud-platform - 将关闭脚本添加到 Dataproc 实例
- python - 如何在 Django 中发送电子邮件验证链接?
- java - 解析布尔表达式问题
- mysql - MariaDB 子表中的外键值显示父表中的重复值
- vue.js - 无法在 NativeScript Vue 模态中访问道具
- java - 这种方法是否可以在线程安全且没有死锁的情况下工作