Merge pull request #2554 from akohlmey/accelerator-introspection

Add accelerator introspection functionality
This commit is contained in:
Axel Kohlmeyer
2021-01-18 11:59:00 -05:00
committed by GitHub
12 changed files with 292 additions and 5 deletions

View File

@ -2,6 +2,7 @@ set(GPU_SOURCES_DIR ${LAMMPS_SOURCE_DIR}/GPU)
set(GPU_SOURCES ${GPU_SOURCES_DIR}/gpu_extra.h
${GPU_SOURCES_DIR}/fix_gpu.h
${GPU_SOURCES_DIR}/fix_gpu.cpp)
target_compile_definitions(lammps PRIVATE -DLMP_GPU)
set(GPU_API "opencl" CACHE STRING "API used by GPU package")
set(GPU_API_VALUES opencl cuda hip)

View File

@ -14,6 +14,7 @@ This section documents the following functions:
- :cpp:func:`lammps_config_has_package`
- :cpp:func:`lammps_config_package_count`
- :cpp:func:`lammps_config_package_name`
- :cpp:func:`lammps_config_accelerator`
- :cpp:func:`lammps_has_style`
- :cpp:func:`lammps_style_count`
- :cpp:func:`lammps_style_name`
@ -126,6 +127,11 @@ approach.
-----------------------
.. doxygenfunction:: lammps_config_accelerator
:project: progguide
-----------------------
.. doxygenfunction:: lammps_has_style
:project: progguide

View File

@ -39,7 +39,9 @@ about compile time settings and included packages and styles.
* :py:attr:`lammps.has_jpeg_support <lammps.lammps.has_jpeg_support>`
* :py:attr:`lammps.has_ffmpeg_support <lammps.lammps.has_ffmpeg_support>`
* :py:attr:`lammps.installed_packages <lammps.lammps.installed_pages>`
* :py:attr:`lammps.installed_packages <lammps.lammps.installed_packages>`
* :py:meth:`lammps.get_accelerator_config <lammps.lammps.accelerator_config>`
* :py:meth:`lammps.has_style() <lammps.lammps.has_style()>`
* :py:meth:`lammps.available_styles() <lammps.lammps.available_styles()>`

View File

@ -10,7 +10,7 @@ Syntax
info args
* args = one or more of the following keywords: *out*\ , *all*\ , *system*\ , *memory*\ , *communication*\ , *computes*\ , *dumps*\ , *fixes*\ , *groups*\ , *regions*\ , *variables*\ , *coeffs*\ , *styles*\ , *time*\ , or *configuration*
* args = one or more of the following keywords: *out*\ , *all*\ , *system*\ , *memory*\ , *communication*\ , *computes*\ , *dumps*\ , *fixes*\ , *groups*\ , *regions*\ , *variables*\ , *coeffs*\ , *styles*\ , *time*\ , *accelerator*\ , or *configuration*
* *out* values = *screen*\ , *log*\ , *append* filename, *overwrite* filename
* *styles* values = *all*\ , *angle*\ , *atom*\ , *bond*\ , *compute*\ , *command*\ , *dump*\ , *dihedral*\ , *fix*\ , *improper*\ , *integrate*\ , *kspace*\ , *minimize*\ , *pair*\ , *region*
@ -88,6 +88,10 @@ The *coeffs* category prints a list for each defined force style
corresponding coefficients have been set. This can be very helpful
to debug error messages like "All pair coeffs are not set".
The *accelerator* category prints out information about compile time
settings of included accelerator support for the GPU, KOKKOS, USER-INTEL,
and USER-OMP packages.
The *styles* category prints the list of styles available in the
current LAMMPS binary. It supports one of the following options
to control which category of styles is printed out:

View File

@ -783,3 +783,39 @@ double lmp_gpu_forces(double **f, double **tor, double *eatom,
double **vatom, double *virial, double &ecoul) {
return global_device.fix_gpu(f,tor,eatom,vatom,virial,ecoul);
}
bool lmp_gpu_config(const std::string &category, const std::string &setting)
{
if (category == "api") {
#if defined(USE_OPENCL)
return setting == "opencl";
#elif defined(USE_HIP)
return setting == "hip";
#elif defined(USE_CUDA)
return setting == "cuda";
#endif
return false;
}
if (category == "precision") {
if (setting == "single") {
#if defined(_SINGLE_SINGLE)
return true;
#else
return false;
#endif
} else if (setting == "mixed") {
#if defined(_SINGLE_DOUBLE)
return true;
#else
return false;
#endif
} else if (setting == "double") {
#if defined(_DOUBLE_DOUBLE)
return true;
#else
return false;
#endif
} else return false;
}
return false;
}

View File

@ -243,6 +243,7 @@ class lammps(object):
self.lib.lammps_encode_image_flags.restype = self.c_imageint
self.lib.lammps_config_package_name.argtypes = [c_int, c_char_p, c_int]
self.lib.lammps_config_accelerator.argtypes = [c_char_p, c_char_p, c_char_p]
self.lib.lammps_set_variable.argtypes = [c_void_p, c_char_p, c_char_p]
@ -1435,6 +1436,36 @@ class lammps(object):
# -------------------------------------------------------------------------
@property
def accelerator_config(self):
""" Return table with available accelerator configuration settings.
This is a wrapper around the :cpp:func:`lammps_config_accelerator`
function of the library interface which loops over all known packages
and categories and returns enabled features as a nested dictionary
with all enabled settings as list of strings.
:return: nested dictionary with all known enabled settings as list of strings
:rtype: dictionary
"""
result = {}
for p in ['GPU', 'KOKKOS', 'USER-INTEL', 'USER-OMP']:
result[p] = {}
c = 'api'
result[p][c] = []
for s in ['cuda', 'hip', 'phi', 'pthreads', 'opencl', 'openmp', 'serial']:
if self.lib.lammps_config_accelerator(p.encode(),c.encode(),s.encode()):
result[p][c].append(s)
c = 'precision'
result[p][c] = []
for s in ['double', 'mixed', 'single']:
if self.lib.lammps_config_accelerator(p.encode(),c.encode(),s.encode()):
result[p][c].append(s)
return result
# -------------------------------------------------------------------------
@property
def installed_packages(self):
""" List of the names of enabled packages in the LAMMPS shared library

View File

@ -152,6 +152,8 @@ if (test $1 = 1) then
if (test -e ../Makefile.package) then
sed -i -e 's/[^ \t]*gpu[^ \t]* //' ../Makefile.package
sed -i -e 's/[^ \t]*GPU[^ \t]* //' ../Makefile.package
sed -i -e 's|^PKG_INC =[ \t]*|&-DLMP_GPU |' ../Makefile.package
sed -i -e 's|^PKG_PATH =[ \t]*|&-L../../lib/gpu |' ../Makefile.package
sed -i -e 's|^PKG_LIB =[ \t]*|&-lgpu |' ../Makefile.package
sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(gpu_SYSINC) |' ../Makefile.package
@ -171,6 +173,7 @@ elif (test $1 = 0) then
if (test -e ../Makefile.package) then
sed -i -e 's/[^ \t]*gpu[^ \t]* //' ../Makefile.package
sed -i -e 's/[^ \t]*GPU[^ \t]* //' ../Makefile.package
fi
if (test -e ../Makefile.package.settings) then

View File

@ -94,6 +94,7 @@ enum {COMPUTES=1<<0,
REGION_STYLES=1<<23,
DUMP_STYLES=1<<24,
COMMAND_STYLES=1<<25,
ACCELERATOR=1<<26,
ALL=~0};
static const int STYLES = ATOM_STYLES | INTEGRATE_STYLES | MINIMIZE_STYLES
@ -198,6 +199,9 @@ void Info::command(int narg, char **arg)
} else if (strncmp(arg[idx],"coeffs",3) == 0) {
flags |= COEFFS;
++idx;
} else if (strncmp(arg[idx],"accelerator",3) == 0) {
flags |= ACCELERATOR;
++idx;
} else if (strncmp(arg[idx],"styles",3) == 0) {
if (idx+1 < narg) {
++idx;
@ -314,6 +318,59 @@ void Info::command(int narg, char **arg)
fputs("\n",out);
}
if (flags & ACCELERATOR) {
fputs("\nAccelerator configuration:\n\n",out);
std::string mesg;
if (has_package("GPU")) {
mesg = "GPU package API:";
if (has_accelerator_feature("GPU","api","cuda")) mesg += " CUDA";
if (has_accelerator_feature("GPU","api","hip")) mesg += " HIP";
if (has_accelerator_feature("GPU","api","opencl")) mesg += " OpenCL";
mesg += "\nGPU package precision:";
if (has_accelerator_feature("GPU","precision","single")) mesg += " single";
if (has_accelerator_feature("GPU","precision","mixed")) mesg += " mixed";
if (has_accelerator_feature("GPU","precision","double")) mesg += " double";
mesg += "\n";
fputs(mesg.c_str(),out);
}
if (has_package("KOKKOS")) {
mesg = "KOKKOS package API:";
if (has_accelerator_feature("KOKKOS","api","cuda")) mesg += " CUDA";
if (has_accelerator_feature("KOKKOS","api","hip")) mesg += " HIP";
if (has_accelerator_feature("KOKKOS","api","openmp")) mesg += " OpenMP";
if (has_accelerator_feature("KOKKOS","api","serial")) mesg += " Serial";
if (has_accelerator_feature("KOKKOS","api","pthreads")) mesg += " Pthreads";
mesg += "\nKOKKOS package precision:";
if (has_accelerator_feature("KOKKOS","precision","single")) mesg += " single";
if (has_accelerator_feature("KOKKOS","precision","mixed")) mesg += " mixed";
if (has_accelerator_feature("KOKKOS","precision","double")) mesg += " double";
mesg += "\n";
fputs(mesg.c_str(),out);
}
if (has_package("USER-OMP")) {
mesg = "USER-OMP package API:";
if (has_accelerator_feature("USER-OMP","api","openmp")) mesg += " OpenMP";
if (has_accelerator_feature("USER-OMP","api","serial")) mesg += " Serial";
mesg += "\nUSER-OMP package precision:";
if (has_accelerator_feature("USER-OMP","precision","single")) mesg += " single";
if (has_accelerator_feature("USER-OMP","precision","mixed")) mesg += " mixed";
if (has_accelerator_feature("USER-OMP","precision","double")) mesg += " double";
mesg += "\n";
fputs(mesg.c_str(),out);
}
if (has_package("USER-INTEL")) {
mesg = "USER-INTEL package API:";
if (has_accelerator_feature("USER-INTEL","api","phi")) mesg += " Phi";
if (has_accelerator_feature("USER-INTEL","api","openmp")) mesg += " OpenMP";
mesg += "\nUSER-INTEL package precision:";
if (has_accelerator_feature("USER-INTEL","precision","single")) mesg += " single";
if (has_accelerator_feature("USER-INTEL","precision","mixed")) mesg += " mixed";
if (has_accelerator_feature("USER-INTEL","precision","double")) mesg += " double";
mesg += "\n";
fputs(mesg.c_str(),out);
}
}
if (flags & MEMORY) {
double meminfo[3];
@ -1120,15 +1177,97 @@ bool Info::has_exceptions() {
#endif
}
bool Info::has_package(const char * package_name) {
bool Info::has_package(const std::string &package_name) {
for (int i = 0; LAMMPS::installed_packages[i] != nullptr; ++i) {
if (strcmp(package_name, LAMMPS::installed_packages[i]) == 0) {
if (package_name == LAMMPS::installed_packages[i]) {
return true;
}
}
return false;
}
#if defined(LMP_GPU)
extern bool lmp_gpu_config(const std::string &, const std::string &);
#endif
#if defined(LMP_KOKKOS)
#include "Kokkos_Macros.hpp"
#endif
bool Info::has_accelerator_feature(const std::string &package,
const std::string &category,
const std::string &setting)
{
#if defined(LMP_KOKKOS)
if (package == "KOKKOS") {
if (category == "precision") {
if (setting == "double") return true;
else return false;
}
if (category == "api") {
#if defined(KOKKOS_ENABLE_OPENMP)
if (setting == "openmp") return true;
#endif
#if defined(KOKKOS_ENABLE_SERIAL)
if (setting == "serial") return true;
#endif
#if defined(KOKKOS_ENABLE_THREADS)
if (setting == "pthreads") return true;
#endif
#if defined(KOKKOS_ENABLE_CUDA)
if (setting == "cuda") return true;
#endif
#if defined(KOKKOS_ENABLE_HIP)
if (setting == "hip") return true;
#endif
return false;
}
}
#endif
#if defined(LMP_GPU)
if (package == "GPU") {
return lmp_gpu_config(category,setting);
}
#endif
#if defined(LMP_USER_OMP)
if (package == "USER-OMP") {
if (category == "precision") {
if (setting == "double") return true;
else return false;
}
if (category == "api") {
#if defined(_OPENMP)
if (setting == "openmp") return true;
#else
if (setting == "serial") return true;
#endif
return false;
}
}
#endif
#if defined(LMP_USER_INTEL)
if (package == "USER-INTEL") {
if (category == "precision") {
if (setting == "double") return true;
else if (setting == "mixed") return true;
else if (setting == "single")return true;
else return false;
}
if (category == "api") {
#if defined(LMP_INTEL_OFFLOAD)
if (setting == "phi") return true;
#elif defined(_OPENMP)
if (setting == "openmp") return true;
#else
if (setting == "serial") return true;
#endif
return false;
}
}
#endif
return false;
}
/* ---------------------------------------------------------------------- */
#define _INFOBUF_SIZE 256

View File

@ -43,7 +43,10 @@ class Info : protected Pointers {
static bool has_jpeg_support();
static bool has_ffmpeg_support();
static bool has_exceptions();
static bool has_package(const char * package_name);
static bool has_package(const std::string &);
static bool has_accelerator_feature(const std::string &,
const std::string &,
const std::string &);
static std::string get_os_info();
static std::string get_compiler_info();

View File

@ -4303,6 +4303,31 @@ int lammps_config_package_name(int idx, char *buffer, int buf_size) {
return 1;
}
/** Check for compile time settings in accelerator packages included in LAMMPS.
*
\verbatim embed:rst
This function checks availability of compile time settings of included
:doc:`accelerator packages <Speed_packages>` in LAMMPS.
Supported packages names are "GPU", "KOKKOS", "USER-INTEL", and "USER-OMP".
Supported categories are "api" with possible settings "cuda", "hip", "phi",
"pthreads", "opencl", "openmp", and "serial", and "precision" with
possible settings "double", "mixed", and "single". If the combination
of package, category, and setting is available, the function returns 1,
otherwise 0.
\endverbatim
*
* \param package string with the name of the accelerator package
* \param category string with the category name of the setting
* \param setting string with the name of the specific setting
* \return 1 if available, 0 if not.
*/
int lammps_config_accelerator(const char *package,
const char *category,
const char *setting)
{
return Info::has_accelerator_feature(package,category,setting) ? 1 : 0;
}
/* ---------------------------------------------------------------------- */
/** Check if a specific style has been included in LAMMPS

View File

@ -195,6 +195,8 @@ int lammps_config_has_package(const char *);
int lammps_config_package_count();
int lammps_config_package_name(int, char *, int);
int lammps_config_accelerator(const char *, const char *, const char *);
int lammps_has_style(void *, const char *, const char *);
int lammps_style_count(void *, const char *);
int lammps_style_name(void *, const char *, int, char *, int);

View File

@ -123,5 +123,40 @@ class PythonCapabilities(unittest.TestCase):
self.lmp.command('run 10')
self.assertEqual(self.lmp.extract_global('ntimestep'),20)
def test_accelerator_config(self):
settings = self.lmp.accelerator_config
if self.cmake_cache['PKG_USER-OMP']:
if self.cmake_cache['BUILD_OMP']:
self.assertIn('openmp',settings['USER-OMP']['api'])
else:
self.assertIn('serial',settings['USER-OMP']['api'])
self.assertIn('double',settings['USER-OMP']['precision'])
if self.cmake_cache['PKG_USER-INTEL']:
if 'LMP_INTEL_OFFLOAD' in self.cmake_cache.keys():
self.assertIn('phi',settings['USER-INTEL']['api'])
elif self.cmake_cache['BUILD_OMP']:
self.assertIn('openmp',settings['USER-INTEL']['api'])
else:
self.assertIn('serial',settings['USER-INTEL']['api'])
self.assertIn('double',settings['USER-INTEL']['precision'])
self.assertIn('mixed',settings['USER-INTEL']['precision'])
self.assertIn('single',settings['USER-INTEL']['precision'])
if self.cmake_cache['PKG_GPU']:
if self.cmake_cache['GPU_API'].lower() == 'opencl':
self.assertIn('opencl',settings['GPU']['api'])
if self.cmake_cache['GPU_API'].lower() == 'cuda':
self.assertIn('cuda',settings['GPU']['api'])
if self.cmake_cache['GPU_API'].lower() == 'hip':
self.assertIn('hip',settings['GPU']['api'])
if self.cmake_cache['GPU_PREC'].lower() == 'double':
self.assertIn('double',settings['GPU']['precision'])
if self.cmake_cache['GPU_PREC'].lower() == 'mixed':
self.assertIn('mixed',settings['GPU']['precision'])
if self.cmake_cache['GPU_PREC'].lower() == 'single':
self.assertIn('single',settings['GPU']['precision'])
if __name__ == "__main__":
unittest.main()