use mutex to avoid race condition when accessing thermo data during run
This commit is contained in:
@ -121,9 +121,9 @@ void Finish::end(int flag)
|
||||
MPI_Allreduce(&cpu_loop,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
cpu_loop = tmp/nprocs;
|
||||
if (time_loop > 0.0) cpu_loop = cpu_loop/time_loop*100.0;
|
||||
output->thermo->footer();
|
||||
|
||||
if (me == 0) {
|
||||
output->thermo->footer();
|
||||
int ntasks = nprocs * nthreads;
|
||||
utils::logmesg(lmp,"Loop time of {:.6g} on {} procs for {} steps with {} atoms\n\n",
|
||||
time_loop,ntasks,update->nsteps,atom->natoms);
|
||||
|
||||
@ -853,7 +853,11 @@ This differs from :cpp:func:`lammps_get_thermo` in that it does **not**
|
||||
trigger an evaluation. Instead it provides direct access to a read-only
|
||||
location of the last thermo output data and the corresponding keyword
|
||||
strings. How to handle the return value depends on the value of the *what*
|
||||
argument string.
|
||||
argument string. When accessing the data from a concurrent thread while
|
||||
LAMMPS is running, the cache needs to be locked first and then unlocked
|
||||
after the data is obtained, so that the data is not corrupted while
|
||||
reading in case LAMMPS wants to update it at the same time. Outside
|
||||
of a run, the lock/unlock calls have no effect.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -902,6 +906,14 @@ argument string.
|
||||
- actual field data for column
|
||||
- pointer to int, int64_t or double
|
||||
- yes
|
||||
* - lock
|
||||
- acquires lock to thermo data cache
|
||||
- NULL pointer
|
||||
- no
|
||||
* - unlock
|
||||
- releases lock to thermo data cache
|
||||
- NULL pointer
|
||||
- no
|
||||
|
||||
\endverbatim
|
||||
*
|
||||
@ -957,8 +969,14 @@ void *lammps_last_thermo(void *handle, const char *what, int index)
|
||||
} else if (field.type == multitype::LAMMPS_DOUBLE) {
|
||||
val = (void *) &field.data.d;
|
||||
}
|
||||
|
||||
} else if (strcmp(what, "lock") == 0) {
|
||||
th->lock_cache();
|
||||
val = nullptr;
|
||||
} else if (strcmp(what, "unlock") == 0) {
|
||||
th->unlock_cache();
|
||||
val = nullptr;
|
||||
} else val = nullptr;
|
||||
|
||||
}
|
||||
END_CAPTURE
|
||||
return val;
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
@ -100,8 +101,8 @@ static char fmtbuf[512];
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
Thermo::Thermo(LAMMPS *_lmp, int narg, char **arg) :
|
||||
Pointers(_lmp), style(nullptr), vtype(nullptr), field2index(nullptr), argindex1(nullptr),
|
||||
argindex2(nullptr), temperature(nullptr), pressure(nullptr), pe(nullptr)
|
||||
Pointers(_lmp), style(nullptr), vtype(nullptr), cache_mutex(nullptr), field2index(nullptr),
|
||||
argindex1(nullptr), argindex2(nullptr), temperature(nullptr), pressure(nullptr), pe(nullptr)
|
||||
{
|
||||
style = utils::strdup(arg[0]);
|
||||
|
||||
@ -208,6 +209,7 @@ void Thermo::init()
|
||||
ValueTokenizer *format_line = nullptr;
|
||||
if (format_line_user.size()) format_line = new ValueTokenizer(format_line_user);
|
||||
|
||||
lock_cache();
|
||||
field_data.clear();
|
||||
field_data.resize(nfield);
|
||||
std::string format_this, format_line_user_def;
|
||||
@ -277,6 +279,7 @@ void Thermo::init()
|
||||
format[i] += fmt::format("{:<8} = {} ", keyword[i], format_this);
|
||||
}
|
||||
}
|
||||
unlock_cache();
|
||||
|
||||
// chop off trailing blank or add closing bracket if needed and then add newline
|
||||
if (lineflag == ONELINE)
|
||||
@ -320,6 +323,9 @@ void Thermo::init()
|
||||
if (index_press_scalar >= 0) pressure = computes[index_press_scalar];
|
||||
if (index_press_vector >= 0) pressure = computes[index_press_vector];
|
||||
if (index_pe >= 0) pe = computes[index_pe];
|
||||
|
||||
// create mutex to protect access to cached thermo data
|
||||
cache_mutex = new std::mutex;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
@ -366,11 +372,19 @@ void Thermo::header()
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
// called at the end of a run from Finish class
|
||||
|
||||
void Thermo::footer()
|
||||
{
|
||||
if (comm->me == 0) {
|
||||
if (lineflag == YAMLLINE) utils::logmesg(lmp, "...\n");
|
||||
}
|
||||
|
||||
// no more locking for cached thermo data access needed
|
||||
delete cache_mutex;
|
||||
cache_mutex = nullptr;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Thermo::compute(int flag)
|
||||
@ -422,6 +436,7 @@ void Thermo::compute(int flag)
|
||||
}
|
||||
|
||||
// add each thermo value to line with its specific format
|
||||
lock_cache();
|
||||
field_data.clear();
|
||||
field_data.resize(nfield);
|
||||
|
||||
@ -441,6 +456,7 @@ void Thermo::compute(int flag)
|
||||
field_data[ifield] = bivalue;
|
||||
}
|
||||
}
|
||||
unlock_cache();
|
||||
|
||||
// print line to screen and logfile
|
||||
|
||||
@ -579,7 +595,8 @@ void Thermo::modify_params(int narg, char **arg)
|
||||
if (iarg + 2 > narg) error->all(FLERR, "Illegal thermo_modify command");
|
||||
triclinic_general = utils::logical(FLERR, arg[iarg + 1], false, lmp);
|
||||
if (triclinic_general && !domain->triclinic_general)
|
||||
error->all(FLERR,"Thermo_modify triclinic/general cannot be used "
|
||||
error->all(FLERR,
|
||||
"Thermo_modify triclinic/general cannot be used "
|
||||
"if simulation box is not general triclinic");
|
||||
iarg += 2;
|
||||
|
||||
@ -1566,6 +1583,26 @@ int Thermo::evaluate_keyword(const std::string &word, double *answer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
// lock cache for current thermo data
|
||||
|
||||
void Thermo::lock_cache()
|
||||
{
|
||||
// no locking outside of a run
|
||||
if (!cache_mutex) return;
|
||||
cache_mutex->lock();
|
||||
}
|
||||
|
||||
// unlock cache for current thermo data
|
||||
|
||||
void Thermo::unlock_cache()
|
||||
{
|
||||
// no locking outside of a run
|
||||
if (!cache_mutex) return;
|
||||
cache_mutex->unlock();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
extraction of Compute, Fix, Variable results
|
||||
compute/fix are normalized by atoms if returning extensive value
|
||||
|
||||
@ -17,6 +17,10 @@
|
||||
#include "pointers.h"
|
||||
#include <map>
|
||||
|
||||
namespace std {
|
||||
class mutex;
|
||||
}
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class Thermo : protected Pointers {
|
||||
@ -43,6 +47,8 @@ class Thermo : protected Pointers {
|
||||
int evaluate_keyword(const std::string &, double *);
|
||||
|
||||
// for accessing cached thermo and related data
|
||||
void lock_cache();
|
||||
void unlock_cache();
|
||||
const int *get_line() const { return &nline; }
|
||||
const char *get_image_fname() const { return image_fname.c_str(); }
|
||||
|
||||
@ -82,6 +88,9 @@ class Thermo : protected Pointers {
|
||||
int nline;
|
||||
std::string image_fname;
|
||||
|
||||
// mutex for locking the cache
|
||||
std::mutex *cache_mutex;
|
||||
|
||||
// data used by routines that compute single values
|
||||
|
||||
int ivalue; // integer value to print
|
||||
|
||||
@ -61,6 +61,8 @@
|
||||
Highlight warnings and error messages in Output window
|
||||
Make Tutorial wizards more compact
|
||||
Include download and compilation of WHAM software from Alan Grossfield
|
||||
Add dialog to run WHAM directly from LAMMPS-GUI
|
||||
Use mutex to avoid corruption of thermo data
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.6.11" timestamp="1725080055">
|
||||
|
||||
@ -1015,6 +1015,7 @@ void LammpsGui::logupdate()
|
||||
void *ptr = lammps.last_thermo("setup", 0);
|
||||
if (ptr && *(int *)ptr) return;
|
||||
|
||||
lammps.last_thermo("lock", 0);
|
||||
ptr = lammps.last_thermo("num", 0);
|
||||
if (ptr) {
|
||||
int ncols = *(int *)ptr;
|
||||
@ -1066,6 +1067,7 @@ void LammpsGui::logupdate()
|
||||
chartwindow->add_data(step, data, i);
|
||||
}
|
||||
}
|
||||
lammps.last_thermo("unlock", 0);
|
||||
}
|
||||
|
||||
// update list of available image file names
|
||||
|
||||
Reference in New Issue
Block a user