diff --git a/cmake/Modules/Packages/GPU.cmake b/cmake/Modules/Packages/GPU.cmake index cad6e2bf9a..bc66ef04d2 100644 --- a/cmake/Modules/Packages/GPU.cmake +++ b/cmake/Modules/Packages/GPU.cmake @@ -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) diff --git a/doc/src/Library_config.rst b/doc/src/Library_config.rst index 24c412a23d..a5b87e23a7 100644 --- a/doc/src/Library_config.rst +++ b/doc/src/Library_config.rst @@ -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 diff --git a/doc/src/Python_config.rst b/doc/src/Python_config.rst index 2803b041c5..38f0ef0baf 100644 --- a/doc/src/Python_config.rst +++ b/doc/src/Python_config.rst @@ -39,7 +39,9 @@ about compile time settings and included packages and styles. * :py:attr:`lammps.has_jpeg_support ` * :py:attr:`lammps.has_ffmpeg_support ` -* :py:attr:`lammps.installed_packages ` +* :py:attr:`lammps.installed_packages ` + +* :py:meth:`lammps.get_accelerator_config ` * :py:meth:`lammps.has_style() ` * :py:meth:`lammps.available_styles() ` diff --git a/doc/src/info.rst b/doc/src/info.rst index 77d430ea66..395bc2c1f4 100644 --- a/doc/src/info.rst +++ b/doc/src/info.rst @@ -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: diff --git a/lib/gpu/lal_device.cpp b/lib/gpu/lal_device.cpp index 6c6a206307..911cdda383 100644 --- a/lib/gpu/lal_device.cpp +++ b/lib/gpu/lal_device.cpp @@ -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; +} diff --git a/python/lammps/core.py b/python/lammps/core.py index c0cbaac533..fe23fa587c 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -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 diff --git a/src/GPU/Install.sh b/src/GPU/Install.sh index b83423eaa7..1fefb01d42 100755 --- a/src/GPU/Install.sh +++ b/src/GPU/Install.sh @@ -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 diff --git a/src/info.cpp b/src/info.cpp index bb3111cb69..bf6f14a48a 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -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 diff --git a/src/info.h b/src/info.h index e14a2be8db..d8fa23489e 100644 --- a/src/info.h +++ b/src/info.h @@ -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(); diff --git a/src/library.cpp b/src/library.cpp index 7d3f2f8996..557d746226 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -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 ` 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 diff --git a/src/library.h b/src/library.h index 14be4064ea..d98bf426b3 100644 --- a/src/library.h +++ b/src/library.h @@ -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); diff --git a/unittest/python/python-capabilities.py b/unittest/python/python-capabilities.py index 2b47b8ca90..372eecc869 100644 --- a/unittest/python/python-capabilities.py +++ b/unittest/python/python-capabilities.py @@ -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()