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