Я выполняю моделирование методом дискретных элементов, и сейчас я прохожу параллельную программу. До сих пор я успешно запускал код в 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);
static vectors
LeftMirrorVec и 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
создаваться разными потоками без взаимного влияния?
Если нет, пожалуйста, дайте мне несколько советов, как справиться с этим вопросом.
И если требуется более подробная информация, пожалуйста, скажите мне, спасибо.