Unverified Commit 3b8df952 authored by Peter Eastman's avatar Peter Eastman Committed by GitHub
Browse files

Merge pull request #4632 from ex-rzr/make-hip-standard-platform

HIP platform
parents 5ce6a85d 28fb2918
...@@ -353,11 +353,24 @@ IF(OPENMM_BUILD_OPENCL_LIB) ...@@ -353,11 +353,24 @@ IF(OPENMM_BUILD_OPENCL_LIB)
ADD_SUBDIRECTORY(platforms/opencl) ADD_SUBDIRECTORY(platforms/opencl)
ENDIF(OPENMM_BUILD_OPENCL_LIB) ENDIF(OPENMM_BUILD_OPENCL_LIB)
# HIP platform
LIST(APPEND CMAKE_PREFIX_PATH $ENV{ROCM_PATH} /opt/rocm)
FIND_PACKAGE(HIP CONFIG QUIET)
IF(HIP_FOUND)
SET(OPENMM_BUILD_HIP_LIB ON CACHE BOOL "Build OpenMMHIP library for AMD GPUs")
ELSE(HIP_FOUND)
SET(OPENMM_BUILD_HIP_LIB OFF CACHE BOOL "Build OpenMMHIP library for AMD GPUs")
ENDIF(HIP_FOUND)
IF(OPENMM_BUILD_HIP_LIB)
ADD_SUBDIRECTORY(platforms/hip)
ENDIF(OPENMM_BUILD_HIP_LIB)
# Common compute files # Common compute files
SET(OPENMM_BUILD_COMMON OFF CACHE BOOL "Build common files even if CUDA or OpenCL platforms are not built") SET(OPENMM_BUILD_COMMON OFF CACHE BOOL "Build common files even if CUDA or OpenCL platforms are not built")
IF(OPENMM_BUILD_CUDA_LIB OR OPENMM_BUILD_OPENCL_LIB OR OPENMM_BUILD_COMMON) IF(OPENMM_BUILD_CUDA_LIB OR OPENMM_BUILD_OPENCL_LIB OR OPENMM_BUILD_HIP_LIB OR OPENMM_BUILD_COMMON)
ADD_SUBDIRECTORY(platforms/common) ADD_SUBDIRECTORY(platforms/common)
ENDIF() ENDIF()
......
...@@ -177,3 +177,31 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ...@@ -177,3 +177,31 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
9. VkFFT
OpenMM uses the VkFFT library by Dmitrii Tolmachev. It may be used under the
terms of the MIT License:
MIT License
Copyright (c) 2020 - present Dmitrii Tolmachev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
...@@ -104,17 +104,6 @@ For more information, see the OpenMMTools_ website. ...@@ -104,17 +104,6 @@ For more information, see the OpenMMTools_ website.
.. _OpenMMTools: https://github.com/choderalab/openmmtools .. _OpenMMTools: https://github.com/choderalab/openmmtools
OpenMM-HIP
**********
This package adds a new platform that is implemented with AMD's HIP framework.
When running on AMD GPUs, it often has much faster performance than the OpenCL
platform. For information about how to install it, see the OpenMM-HIP_ website.
Once it is installed, the new platform can be selected and used exactly like the
ones included in the main OpenMM package.
.. _OpenMM-HIP: https://github.com/StreamHPC/openmm-hip
openmmforcefields openmmforcefields
***************** *****************
......
...@@ -46,7 +46,7 @@ license. This is a very permissive license which allows them to be used in ...@@ -46,7 +46,7 @@ license. This is a very permissive license which allows them to be used in
almost any way, requiring only that you retain the copyright notice and almost any way, requiring only that you retain the copyright notice and
disclaimer when distributing them. disclaimer when distributing them.
The CUDA and OpenCL platforms are distributed under the GNU Lesser General The CUDA, HIP, and OpenCL platforms are distributed under the GNU Lesser General
Public License (LGPL). This also allows you to use, modify, and distribute them Public License (LGPL). This also allows you to use, modify, and distribute them
in any way you want, but it requires you to also distribute the source code for in any way you want, but it requires you to also distribute the source code for
your modifications. This restriction applies only to modifications to OpenMM your modifications. This restriction applies only to modifications to OpenMM
...@@ -280,8 +280,8 @@ simulation; it is a fairly generic computational API. In addition to defining ...@@ -280,8 +280,8 @@ simulation; it is a fairly generic computational API. In addition to defining
the generic classes, OpenMM also defines abstract subclasses of KernelImpl the generic classes, OpenMM also defines abstract subclasses of KernelImpl
corresponding to specific calculations. For example, there is a class called corresponding to specific calculations. For example, there is a class called
CalcHarmonicBondForceKernel to implement HarmonicBondForce and a class called CalcHarmonicBondForceKernel to implement HarmonicBondForce and a class called
IntegrateLangevinStepKernel to implement LangevinIntegrator. It is these IntegrateLangevinMiddleStepKernel to implement LangevinMiddleIntegrator. It is
classes for which each Platform must provide a concrete subclass. these classes for which each Platform must provide a concrete subclass.
This architecture is designed to allow easy extensibility. To support a new This architecture is designed to allow easy extensibility. To support a new
hardware platform, for example, you create concrete subclasses of all the hardware platform, for example, you create concrete subclasses of all the
...@@ -330,6 +330,9 @@ conventional CPUs. ...@@ -330,6 +330,9 @@ conventional CPUs.
**CudaPlatform**\ : This platform is implemented using the CUDA language, and **CudaPlatform**\ : This platform is implemented using the CUDA language, and
performs calculations on Nvidia GPUs. performs calculations on Nvidia GPUs.
**HipPlatform**\ : This platform is implemented using the HIP language, and
performs calculations on ROCm-compatible AMD GPUs.
**OpenCLPlatform**\ : This platform is implemented using the OpenCL language, **OpenCLPlatform**\ : This platform is implemented using the OpenCL language,
and performs calculations on a variety of types of GPUs and CPUs. and performs calculations on a variety of types of GPUs and CPUs.
...@@ -343,8 +346,8 @@ The choice of which platform to use for a simulation depends on various factors: ...@@ -343,8 +346,8 @@ The choice of which platform to use for a simulation depends on various factors:
some older computers. Also, for simulations that use certain features some older computers. Also, for simulations that use certain features
(primarily the various “custom” force classes), it may be faster to use the (primarily the various “custom” force classes), it may be faster to use the
OpenCL platform running on the CPU. OpenCL platform running on the CPU.
#. The CUDA platform can only be used with NVIDIA GPUs. For using an AMD or #. The CUDA platform can be used with NVIDIA GPUs. For using an AMD GPU,
Intel GPU, use the OpenCL platform. use the HIP platform (or the OpenCL platform which is usually slower), for
#. The AMOEBA force field only works with the CUDA platform, not with the OpenCL using an Intel GPU, use the OpenCL platform.
platform. It also works with the Reference and CPU platforms, but the performance #. The AMOEBA force field works with all platforms, but the performance
is usually too slow to be useful on those platforms. of the Reference and CPU platforms is usually too slow to be useful.
...@@ -111,7 +111,7 @@ There are several variables that can be adjusted in the CMake interface: ...@@ -111,7 +111,7 @@ There are several variables that can be adjusted in the CMake interface:
any reason CMake is unable to find them, set OPENCL_INCLUDE_DIR to point to any reason CMake is unable to find them, set OPENCL_INCLUDE_DIR to point to
the directory containing the headers (usually /usr/local/cuda/include on Linux) the directory containing the headers (usually /usr/local/cuda/include on Linux)
and OPENCL_LIBRARY to point to the library (usually /usr/local/cuda/lib64/libOpenCL.so and OPENCL_LIBRARY to point to the library (usually /usr/local/cuda/lib64/libOpenCL.so
on Linux). on Linux).
Configure (press “c”) again. Adjust any variables that cause an error. Configure (press “c”) again. Adjust any variables that cause an error.
...@@ -167,12 +167,6 @@ fraction of the time. These tests will say so in the error message: ...@@ -167,12 +167,6 @@ fraction of the time. These tests will say so in the error message:
exception: Assertion failure at TestReferenceLangevinIntegrator.cpp:129. Expected 9.97741, exception: Assertion failure at TestReferenceLangevinIntegrator.cpp:129. Expected 9.97741,
found 10.7884 (This test is stochastic and may occasionally fail) found 10.7884 (This test is stochastic and may occasionally fail)
If you get an error message such as :code:`exception: Error launching CUDA compiler: 32512` you need
to specify the path to the CUDA compiler (nvcc) using the :code:`OPENMM_CUDA_COMPILER` environment
variable, for example using something like the following::
OPENMM_CUDA_COMPILER=/<path_to_custom_cuda_dir>/nvcc
Step 3: Install Step 3: Install
=============== ===============
Install your local build of OpenMM using the following command:: Install your local build of OpenMM using the following command::
...@@ -309,7 +303,7 @@ There are several variables that can be adjusted in the CMake interface: ...@@ -309,7 +303,7 @@ There are several variables that can be adjusted in the CMake interface:
the directory containing the headers (usually the directory containing the headers (usually
"C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.4/include", except "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.4/include", except
with the correct version number for the toolkit you installed) and with the correct version number for the toolkit you installed) and
OPENCL_LIBRARY to point to the library (usually "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.4/lib/x64/OpenCL.lib"). OPENCL_LIBRARY to point to the library (usually "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.4/lib/x64/OpenCL.lib").
Press "Configure" again. Adjust any variables that cause an error. Press "Configure" again. Adjust any variables that cause an error.
...@@ -437,4 +431,4 @@ Step 3: Install local build of openmm ...@@ -437,4 +431,4 @@ Step 3: Install local build of openmm
===================================== =====================================
Now we just install our local build of :code:`openmm` as instructed in Now we just install our local build of :code:`openmm` as instructed in
:ref:`compiling-openmm-from-source-linux` :ref:`compiling-openmm-from-source-linux`
\ No newline at end of file
...@@ -152,10 +152,10 @@ ExpressionTreeNode ParsedExpression::substituteSimplerExpression(const Expressio ...@@ -152,10 +152,10 @@ ExpressionTreeNode ParsedExpression::substituteSimplerExpression(const Expressio
else else
children[i] = cached->second; children[i] = cached->second;
} }
// Collect some info on constant expressions in children // Collect some info on constant expressions in children
bool first_const = children.size() > 0 && isConstant(children[0]); // is first child constant? bool first_const = children.size() > 0 && isConstant(children[0]); // is first child constant?
bool second_const = children.size() > 1 && isConstant(children[1]); // is second child constant? bool second_const = children.size() > 1 && isConstant(children[1]); // is second child constant?
double first, second; // if yes, value of first and second child double first, second; // if yes, value of first and second child
if (first_const) if (first_const)
first = getConstantValue(children[0]); first = getConstantValue(children[0]);
...@@ -205,7 +205,7 @@ ExpressionTreeNode ParsedExpression::substituteSimplerExpression(const Expressio ...@@ -205,7 +205,7 @@ ExpressionTreeNode ParsedExpression::substituteSimplerExpression(const Expressio
break; break;
} }
case Operation::MULTIPLY: case Operation::MULTIPLY:
{ {
if ((first_const && first == 0.0) || (second_const && second == 0.0)) // Multiply by 0 if ((first_const && first == 0.0) || (second_const && second == 0.0)) // Multiply by 0
return ExpressionTreeNode(new Operation::Constant(0.0)); return ExpressionTreeNode(new Operation::Constant(0.0));
if (first_const && first == 1.0) // Multiply by 1 if (first_const && first == 1.0) // Multiply by 1
...@@ -247,7 +247,7 @@ ExpressionTreeNode ParsedExpression::substituteSimplerExpression(const Expressio ...@@ -247,7 +247,7 @@ ExpressionTreeNode ParsedExpression::substituteSimplerExpression(const Expressio
case Operation::DIVIDE: case Operation::DIVIDE:
{ {
if (children[0] == children[1]) if (children[0] == children[1])
return ExpressionTreeNode(new Operation::Constant(1.0)); // Dividing anything from itself is 0 return ExpressionTreeNode(new Operation::Constant(1.0)); // Dividing anything by itself is 1
if (first_const && first == 0.0) // 0 divided by something if (first_const && first == 0.0) // 0 divided by something
return ExpressionTreeNode(new Operation::Constant(0.0)); return ExpressionTreeNode(new Operation::Constant(0.0));
if (first_const && first == 1.0) // 1 divided by something if (first_const && first == 1.0) // 1 divided by something
......
#---------------------------------------------------
# OpenMM HIP Platform
#
# Creates OpenMMHIP library.
#
# Windows:
# OpenMMHIP.dll
# OpenMMHIP.lib
# OpenMMHIP_static.lib
# Unix:
# libOpenMMHIP.so
# libOpenMMHIP_static.a
#----------------------------------------------------
FIND_PACKAGE(HIPRTC CONFIG)
SET(OPENMM_BUILD_HIP_TESTS TRUE CACHE BOOL "Whether to build HIP test cases")
IF(BUILD_TESTING AND OPENMM_BUILD_HIP_TESTS)
SUBDIRS(tests)
ENDIF(BUILD_TESTING AND OPENMM_BUILD_HIP_TESTS)
# The source is organized into subdirectories, but we handle them all from
# this CMakeLists file rather than letting CMake visit them as SUBDIRS.
SET(OPENMM_SOURCE_SUBDIRS . ../common)
# Collect up information about the version of the OpenMM library we're building
# and make it available to the code so it can be built into the binaries.
SET(OPENMMHIP_LIBRARY_NAME OpenMMHIP)
SET(SHARED_TARGET ${OPENMMHIP_LIBRARY_NAME})
SET(STATIC_TARGET ${OPENMMHIP_LIBRARY_NAME}_static)
# These are all the places to search for header files which are
# to be part of the API.
SET(API_INCLUDE_DIRS) # start empty
FOREACH(subdir ${OPENMM_SOURCE_SUBDIRS})
# append
SET(API_INCLUDE_DIRS ${API_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/include
${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/include/internal)
ENDFOREACH(subdir)
# We'll need both *relative* path names, starting with their API_INCLUDE_DIRS,
# and absolute pathnames.
SET(API_REL_INCLUDE_FILES) # start these out empty
SET(API_ABS_INCLUDE_FILES)
FOREACH(dir ${API_INCLUDE_DIRS})
FILE(GLOB fullpaths ${dir}/*.h) # returns full pathnames
SET(API_ABS_INCLUDE_FILES ${API_ABS_INCLUDE_FILES} ${fullpaths})
FOREACH(pathname ${fullpaths})
GET_FILENAME_COMPONENT(filename ${pathname} NAME)
SET(API_REL_INCLUDE_FILES ${API_REL_INCLUDE_FILES} ${dir}/${filename})
ENDFOREACH(pathname)
ENDFOREACH(dir)
# collect up source files
SET(SOURCE_FILES) # empty
SET(SOURCE_INCLUDE_FILES)
FOREACH(subdir ${OPENMM_SOURCE_SUBDIRS})
FILE(GLOB_RECURSE src_files ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/src/*.c)
FILE(GLOB incl_files ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/src/*.h)
SET(SOURCE_FILES ${SOURCE_FILES} ${src_files}) #append
IF(MSVC)
FILE(GLOB_RECURSE kernel_files ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/src/kernels/*.hip)
SET(SOURCE_FILES ${SOURCE_FILES} ${kernel_files})
ENDIF(MSVC)
SET(SOURCE_INCLUDE_FILES ${SOURCE_INCLUDE_FILES} ${incl_files})
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}/include)
ENDFOREACH(subdir)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# Encode the kernel sources into a C++ class
SET(KERNEL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
SET(KERNEL_SOURCE_CLASS HipKernelSources)
SET(KERNELS_CPP ${CMAKE_CURRENT_BINARY_DIR}/src/${KERNEL_SOURCE_CLASS}.cpp)
SET(KERNELS_H ${CMAKE_CURRENT_BINARY_DIR}/src/${KERNEL_SOURCE_CLASS}.h)
SET(COMMON_KERNELS_CPP ${CMAKE_CURRENT_BINARY_DIR}/../common/src/CommonKernelSources.cpp)
SET(SOURCE_FILES ${SOURCE_FILES} ${KERNELS_CPP} ${KERNELS_H} ${COMMON_KERNELS_CPP})
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/src)
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/../common/src)
FILE(GLOB HIP_KERNELS ${KERNEL_SOURCE_DIR}/kernels/*.hip)
ADD_CUSTOM_COMMAND(OUTPUT ${KERNELS_CPP} ${KERNELS_H}
COMMAND ${CMAKE_COMMAND}
ARGS -D KERNEL_SOURCE_DIR=${KERNEL_SOURCE_DIR} -D KERNELS_CPP=${KERNELS_CPP} -D KERNELS_H=${KERNELS_H} -D KERNEL_SOURCE_CLASS=${KERNEL_SOURCE_CLASS} -D KERNEL_FILE_EXTENSION=hip -P ${CMAKE_SOURCE_DIR}/cmake_modules/EncodeKernelFiles.cmake
DEPENDS ${HIP_KERNELS}
)
SET_SOURCE_FILES_PROPERTIES(${KERNELS_CPP} ${KERNELS_H} ${COMMON_KERNELS_CPP} PROPERTIES GENERATED TRUE)
ADD_CUSTOM_TARGET(HipKernels DEPENDS ${KERNELS_CPP} ${KERNELS_H})
IF(OPENMM_BUILD_SHARED_LIB)
ADD_LIBRARY(${SHARED_TARGET} SHARED ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_ABS_INCLUDE_FILES})
ADD_DEPENDENCIES(${SHARED_TARGET} CommonKernels HipKernels)
TARGET_LINK_LIBRARIES(${SHARED_TARGET} PUBLIC ${OPENMM_LIBRARY_NAME} ${PTHREADS_LIB} hip::host hiprtc::hiprtc)
SET_TARGET_PROPERTIES(${SHARED_TARGET} PROPERTIES COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_COMMON_BUILDING_SHARED_LIBRARY")
SET_TARGET_PROPERTIES(${SHARED_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}")
INSTALL_TARGETS(/lib/plugins RUNTIME_DIRECTORY /lib/plugins ${SHARED_TARGET})
ENDIF(OPENMM_BUILD_SHARED_LIB)
# Build the static library.
IF(OPENMM_BUILD_STATIC_LIB)
ADD_LIBRARY(${STATIC_TARGET} STATIC ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_ABS_INCLUDE_FILES})
ADD_DEPENDENCIES(${STATIC_TARGET} CommonKernels HipKernels)
TARGET_LINK_LIBRARIES(${STATIC_TARGET} ${OPENMM_LIBRARY_NAME} ${PTHREADS_LIB_STATIC} hip::host hiprtc::hiprtc)
SET_TARGET_PROPERTIES(${STATIC_TARGET} PROPERTIES COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_COMMON_BUILDING_STATIC_LIBRARY")
SET_TARGET_PROPERTIES(${STATIC_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}")
INSTALL_TARGETS(/lib/plugins RUNTIME_DIRECTORY /lib/plugins ${STATIC_TARGET})
ENDIF(OPENMM_BUILD_STATIC_LIB)
# Install headers
FILE(GLOB CORE_HEADERS include/*.h ${KERNELS_H})
INSTALL_FILES(/include/openmm/hip FILES ${CORE_HEADERS})
#ifndef OPENMM_HIPARRAY_H_
#define OPENMM_HIPARRAY_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009-2022 Stanford University and the Authors. *
* Portions copyright (c) 2020-2022 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/OpenMMException.h"
#include "openmm/common/windowsExportCommon.h"
#include "openmm/common/ArrayInterface.h"
#include <hip/hip_runtime.h>
#include <iostream>
#include <sstream>
#include <vector>
namespace OpenMM {
class HipContext;
/**
* This class encapsulates a block of HIP device memory. It provides a simplified API
* for working with it and for copying data to and from device memory.
*/
class OPENMM_EXPORT_COMMON HipArray : public ArrayInterface {
public:
/**
* Create a HipArray object. The object is allocated on the heap with the "new" operator.
* The template argument is the data type of each array element.
*
* @param context the context for which to create the array
* @param size the number of elements in the array
* @param name the name of the array
*/
template <class T>
static HipArray* create(HipContext& context, size_t size, const std::string& name) {
return new HipArray(context, size, sizeof(T), name);
}
/**
* Create an uninitialized HipArray object. It does not point to any device memory,
* and cannot be used until initialize() is called on it.
*/
HipArray();
/**
* Create a HipArray object.
*
* @param context the context for which to create the array
* @param size the number of elements in the array
* @param elementSize the size of each element in bytes
* @param name the name of the array
*/
HipArray(HipContext& context, size_t size, int elementSize, const std::string& name);
~HipArray();
/**
* Initialize this object.
*
* @param context the context for which to create the array
* @param size the number of elements in the array
* @param elementSize the size of each element in bytes
* @param name the name of the array
*/
void initialize(ComputeContext& context, size_t size, int elementSize, const std::string& name);
/**
* Initialize this object. The template argument is the data type of each array element.
*
* @param context the context for which to create the array
* @param size the number of elements in the array
* @param name the name of the array
*/
template <class T>
void initialize(ComputeContext& context, size_t size, const std::string& name) {
initialize(context, size, sizeof(T), name);
}
/**
* Recreate the internal storage to have a different size.
*/
void resize(size_t size);
/**
* Get whether this array has been initialized.
*/
bool isInitialized() const {
return (pointer != 0);
}
/**
* Get the number of elements in the array.
*/
size_t getSize() const {
return size;
}
/**
* Get the size of each element in bytes.
*/
int getElementSize() const {
return elementSize;
}
/**
* Get the name of the array.
*/
const std::string& getName() const {
return name;
}
/**
* Get the context this array belongs to.
*/
ComputeContext& getContext();
/**
* Get a pointer to the device memory.
*/
hipDeviceptr_t& getDevicePointer() {
return pointer;
}
/**
* Copy the values in a vector to the device memory.
*/
template <class T>
void upload(const std::vector<T>& data, bool convert=false) {
ArrayInterface::upload(data, convert);
}
/**
* Copy the values in the Buffer to a vector.
*/
template <class T>
void download(std::vector<T>& data) const {
ArrayInterface::download(data);
}
/**
* Copy the values from host memory to the array.
*
* @param data the data to copy
* @param blocking if true, this call will block until the transfer is complete. If false,
* the source array must be in page-locked memory.
*/
void upload(const void* data, bool blocking=true) {
uploadSubArray(data, 0, getSize(), blocking);
}
/**
* Copy values from host memory to a subset of the array.
*
* @param data the data to copy
* @param offset the index of the element within the array at which the copy should begin
* @param elements the number of elements to copy
* @param blocking if true, this call will block until the transfer is complete. If false,
* the source array must be in page-locked memory.
*/
void uploadSubArray(const void* data, int offset, int elements, bool blocking=true);
/**
* Copy the values in the device memory to an array.
*
* @param data the array to copy the memory to
* @param blocking if true, this call will block until the transfer is complete. If false,
* the destination array must be in page-locked memory.
*/
void download(void* data, bool blocking=true) const;
/**
* Copy the values in the device memory to a second array.
*
* @param dest the destination array to copy to
*/
void copyTo(ArrayInterface& dest) const;
private:
HipContext* context;
hipDeviceptr_t pointer;
size_t size;
int elementSize;
bool ownsMemory;
std::string name;
};
} // namespace OpenMM
#endif /*OPENMM_HIPARRAY_H_*/
#ifndef OPENMM_HIPBONDEDUTILITIES_H_
#define OPENMM_HIPBONDEDUTILITIES_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2011-2024 Stanford University and the Authors. *
* Portions copyright (c) 2020 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/common/BondedUtilities.h"
#include "openmm/common/windowsExportCommon.h"
namespace OpenMM {
/**
* This class exists only for backward compatibility. It adds no features beyond
* the base BondedUtilities class.
*/
class OPENMM_EXPORT_COMMON HipBondedUtilities : public BondedUtilities {
public:
HipBondedUtilities(ComputeContext& context) : BondedUtilities(context) {
}
};
} // namespace OpenMM
#endif /*OPENMM_HIPBONDEDUTILITIES_H_*/
This diff is collapsed.
#ifndef OPENMM_HIPEVENT_H_
#define OPENMM_HIPEVENT_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2019 Stanford University and the Authors. *
* Portions copyright (c) 2020 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "HipContext.h"
#include "openmm/common/ComputeEvent.h"
namespace OpenMM {
/**
* This is the HIP implementation of the ComputeKernelImpl interface.
*/
class HipEvent : public ComputeEventImpl {
public:
HipEvent(HipContext& context);
~HipEvent();
/**
* Place the event into the device's execution queue.
*/
void enqueue();
/**
* Block until all operations started before the call to enqueue() have completed.
*/
void wait();
private:
HipContext& context;
hipEvent_t event;
bool eventCreated;
};
} // namespace OpenMM
#endif /*OPENMM_HIPEVENT_H_*/
#ifndef OPENMM_HIPEXPRESSIONUTILITIES_H_
#define OPENMM_HIPEXPRESSIONUTILITIES_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2019 Stanford University and the Authors. *
* Portions copyright (c) 2020 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/common/ExpressionUtilities.h"
#include "openmm/common/windowsExportCommon.h"
namespace OpenMM {
/**
* This class exists only for backward compatibility. It adds no features beyond
* the base ExpressionUtilities class.
*/
class OPENMM_EXPORT_COMMON HipExpressionUtilities : public ExpressionUtilities {
public:
HipExpressionUtilities(ComputeContext& context) : ExpressionUtilities(context) {
}
};
} // namespace OpenMM
#endif /*OPENMM_HIPEXPRESSIONUTILITIES_H_*/
#ifndef __OPENMM_HIPFFT3D_H__
#define __OPENMM_HIPFFT3D_H__
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009-2015 Stanford University and the Authors. *
* Portions copyright (c) 2021 Advanced Micro Devices, Inc. *
* Authors: *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "HipArray.h"
#define VKFFT_BACKEND 2 // HIP
#include "vkFFT.h"
namespace OpenMM {
class HipContext;
/**
* This class performs three dimensional Fast Fourier Transforms using VkFFT by
* Dmitrii Tolmachev (https://github.com/DTolm/VkFFT).
* <p>
* Note that this class performs an unnormalized transform. That means that if you perform
* a forward transform followed immediately by an inverse transform, the effect is to
* multiply every value of the original data set by the total number of data points.
*/
class OPENMM_EXPORT_COMMON HipFFT3D {
public:
/**
* Create an HipFFT3D object for performing transforms of a particular size.
* <p>
* The transform cannot be done in-place: the input and output
* arrays must be different. Also, the input array is used as workspace, so its contents
* are destroyed. This also means that both arrays must be large enough to hold complex values,
* even when performing a real-to-complex transform.
* <p>
* When performing a real-to-complex transform, the output data is of size xsize*ysize*(zsize/2+1)
* and contains only the non-redundant elements.
*
* @param context the context in which to perform calculations
* @param xsize the first dimension of the data sets on which FFTs will be performed
* @param ysize the second dimension of the data sets on which FFTs will be performed
* @param zsize the third dimension of the data sets on which FFTs will be performed
* @param realToComplex if true, a real-to-complex transform will be done. Otherwise, it is complex-to-complex.
* @param stream HIP stream
* @param in the data to transform, ordered such that in[x*ysize*zsize + y*zsize + z] contains element (x, y, z)
* @param out on exit, this contains the transformed data
*/
HipFFT3D(HipContext& context, int xsize, int ysize, int zsize, bool realToComplex, hipStream_t stream, HipArray& in, HipArray& out);
~HipFFT3D();
/**
* Perform a Fourier transform.
*
* @param forward true to perform a forward transform, false to perform an inverse transform
*/
void execFFT(bool forward);
/**
* Get the smallest legal size for a dimension of the grid (that is, a size with no prime
* factors other than 2, 3, 5, 7, 11, 13). VkFFT supports arbitrary sizes but they may work
* slower.
*
* @param minimum the minimum size the return value must be greater than or equal to
*/
static int findLegalDimension(int minimum);
private:
hipStream_t stream;
HipContext& context;
int deviceIndex;
void* inputBuffer;
void* outputBuffer;
uint64_t inputBufferSize;
uint64_t outputBufferSize;
VkFFTApplication* app;
};
} // namespace OpenMM
#endif // __OPENMM_HIPFFT3D_H__
#ifndef OPENMM_HIPFORCEINFO_H_
#define OPENMM_HIPFORCEINFO_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009 Stanford University and the Authors. *
* Portions copyright (c) 2020 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/common/ComputeForceInfo.h"
#include "openmm/common/windowsExportCommon.h"
#include <vector>
namespace OpenMM {
/**
* This class exists solely for backward compatibility. It adds no features beyond the ones
* in ComputeForceInfo.
*/
class OPENMM_EXPORT_COMMON HipForceInfo : public ComputeForceInfo {
};
} // namespace OpenMM
#endif /*OPENMM_HIPFORCEINFO_H_*/
#ifndef OPENMM_HIPINTEGRATIONUTILITIES_H_
#define OPENMM_HIPINTEGRATIONUTILITIES_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009-2019 Stanford University and the Authors. *
* Portions copyright (c) 2020 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "HipArray.h"
#include "openmm/System.h"
#include "openmm/common/IntegrationUtilities.h"
#include "openmm/common/windowsExportCommon.h"
#include <hip/hip_runtime.h>
namespace OpenMM {
class HipContext;
/**
* This class implements features that are used by many different integrators, including
* common workspace arrays, random number generation, and enforcing constraints.
*/
class OPENMM_EXPORT_COMMON HipIntegrationUtilities : public IntegrationUtilities {
public:
HipIntegrationUtilities(HipContext& context, const System& system);
~HipIntegrationUtilities();
/**
* Get the array which contains position deltas.
*/
HipArray& getPosDelta();
/**
* Get the array which contains random values. Each element is a float4, whose components
* are independent, normally distributed random numbers with mean 0 and variance 1.
*/
HipArray& getRandom();
/**
* Get the array which contains the current step size.
*/
HipArray& getStepSize();
/**
* Distribute forces from virtual sites to the atoms they are based on.
*/
void distributeForcesFromVirtualSites();
private:
void applyConstraintsImpl(bool constrainVelocities, double tol);
int* ccmaConvergedMemory;
hipDeviceptr_t ccmaConvergedDeviceMemory;
hipEvent_t ccmaEvent;
};
} // namespace OpenMM
#endif /*OPENMM_HIPINTEGRATIONUTILITIES_H_*/
#ifndef OPENMM_HIPKERNEL_H_
#define OPENMM_HIPKERNEL_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2019 Stanford University and the Authors. *
* Portions copyright (c) 2020 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "HipArray.h"
#include "HipContext.h"
#include <string>
#include <vector>
namespace OpenMM {
/**
* This is the HIP implementation of the ComputeKernelImpl interface.
*/
class HipKernel : public ComputeKernelImpl {
public:
/**
* Create a new HipKernel.
*
* @param context the context this kernel belongs to
* @param kernel the kernel to be invoked
* @param name the name of the kernel function
*/
HipKernel(HipContext& context, hipFunction_t kernel, const std::string& name);
/**
* Get the name of this kernel.
*/
std::string getName() const;
/**
* Get the maximum block size that can be used when executing this kernel.
*/
int getMaxBlockSize() const;
/**
* Execute this kernel.
*
* @param threads the maximum number of threads that should be used. Depending on the
* computing device, it may choose to use fewer threads than this number.
* @param blockSize the number of threads in each thread block. If this is omitted, a
* default size that is appropriate for the computing device is used.
*/
void execute(int threads, int blockSize=-1);
protected:
/**
* Add an argument to pass the kernel when it is invoked, where the value is a
* subclass of ArrayInterface.
*
* @param value the value to pass to the kernel
*/
void addArrayArg(ArrayInterface& value);
/**
* Add an argument to pass the kernel when it is invoked, where the value is a primitive type.
*
* @param value a pointer to the argument value
* @param size the size of the value in bytes
*/
void addPrimitiveArg(const void* value, int size);
/**
* Add a placeholder for an argument without specifying its value.
*/
void addEmptyArg();
/**
* Add an argument to pass the kernel when it is invoked, where the value is a
* subclass of ArrayInterface.
*
* @param index the index of the argument to set
* @param value the value to pass to the kernel
*/
void setArrayArg(int index, ArrayInterface& value);
/**
* Add an argument to pass the kernel when it is invoked, where the value is a primitive type.
*
* @param index the index of the argument to set
* @param value a pointer to the argument value
* @param size the size of the value in bytes
*/
void setPrimitiveArg(int index, const void* value, int size);
private:
HipContext& context;
hipFunction_t kernel;
std::string name;
std::vector<double4> primitiveArgs;
std::vector<HipArray*> arrayArgs;
std::vector<void*> argPointers;
};
} // namespace OpenMM
#endif /*OPENMM_HIPKERNEL_H_*/
#ifndef OPENMM_HIPKERNELFACTORY_H_
#define OPENMM_HIPKERNELFACTORY_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2012 Stanford University and the Authors. *
* Portions copyright (c) 2020 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/KernelFactory.h"
namespace OpenMM {
/**
* This KernelFactory creates all kernels for HipPlatform.
*/
class HipKernelFactory : public KernelFactory {
public:
KernelImpl* createKernelImpl(std::string name, const Platform& platform, ContextImpl& context) const;
};
} // namespace OpenMM
#endif /*OPENMM_HIPKERNELFACTORY_H_*/
#ifndef OPENMM_HIPKERNELS_H_
#define OPENMM_HIPKERNELS_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Portions copyright (c) 2020-2022 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "HipPlatform.h"
#include "HipArray.h"
#include "HipContext.h"
#include "HipFFT3D.h"
#include "HipSort.h"
#include "openmm/kernels.h"
#include "openmm/System.h"
#include "openmm/common/CommonKernels.h"
namespace OpenMM {
/**
* This kernel is invoked at the beginning and end of force and energy computations. It gives the
* Platform a chance to clear buffers and do other initialization at the beginning, and to do any
* necessary work at the end to determine the final results.
*/
class HipCalcForcesAndEnergyKernel : public CalcForcesAndEnergyKernel {
public:
HipCalcForcesAndEnergyKernel(std::string name, const Platform& platform, HipContext& cu) : CalcForcesAndEnergyKernel(name, platform), cu(cu) {
}
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
*/
void initialize(const System& system);
/**
* This is called at the beginning of each force/energy computation, before calcForcesAndEnergy() has been called on
* any ForceImpl.
*
* @param context the context in which to execute this kernel
* @param includeForce true if forces should be computed
* @param includeEnergy true if potential energy should be computed
* @param groups a set of bit flags for which force groups to include
*/
void beginComputation(ContextImpl& context, bool includeForce, bool includeEnergy, int groups);
/**
* This is called at the end of each force/energy computation, after calcForcesAndEnergy() has been called on
* every ForceImpl.
*
* @param context the context in which to execute this kernel
* @param includeForce true if forces should be computed
* @param includeEnergy true if potential energy should be computed
* @param groups a set of bit flags for which force groups to include
* @param valid the method may set this to false to indicate the results are invalid and the force/energy
* calculation should be repeated
* @return the potential energy of the system. This value is added to all values returned by ForceImpls'
* calcForcesAndEnergy() methods. That is, each force kernel may <i>either</i> return its contribution to the
* energy directly, <i>or</i> add it to an internal buffer so that it will be included here.
*/
double finishComputation(ContextImpl& context, bool includeForce, bool includeEnergy, int groups, bool& valid);
private:
HipContext& cu;
};
/**
* This kernel is invoked by NonbondedForce to calculate the forces acting on the system.
*/
class HipCalcNonbondedForceKernel : public CalcNonbondedForceKernel {
public:
HipCalcNonbondedForceKernel(std::string name, const Platform& platform, HipContext& cu, const System& system) : CalcNonbondedForceKernel(name, platform),
cu(cu), hasInitializedFFT(false), sort(NULL), dispersionFft(NULL), fft(NULL), pmeio(NULL), usePmeStream(false) {
}
~HipCalcNonbondedForceKernel();
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param force the NonbondedForce this kernel will be used for
*/
void initialize(const System& system, const NonbondedForce& force);
/**
* Execute the kernel to calculate the forces and/or energy.
*
* @param context the context in which to execute this kernel
* @param includeForces true if forces should be calculated
* @param includeEnergy true if the energy should be calculated
* @param includeDirect true if direct space interactions should be included
* @param includeReciprocal true if reciprocal space interactions should be included
* @return the potential energy due to the force
*/
double execute(ContextImpl& context, bool includeForces, bool includeEnergy, bool includeDirect, bool includeReciprocal);
/**
* Copy changed parameters over to a context.
*
* @param context the context to copy parameters to
* @param force the NonbondedForce to copy the parameters from
*/
void copyParametersToContext(ContextImpl& context, const NonbondedForce& force);
/**
* Get the parameters being used for PME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
/**
* Get the dispersion parameters being used for the dispersion term in LJPME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void getLJPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private:
class SortTrait : public HipSort::SortTrait {
int getDataSize() const {return 8;}
int getKeySize() const {return 4;}
const char* getDataType() const {return "int2";}
const char* getKeyType() const {return "int";}
const char* getMinKey() const {return "(-2147483647-1)";}
const char* getMaxKey() const {return "2147483647";}
const char* getMaxValue() const {return "make_int2(2147483647, 2147483647)";}
const char* getSortKey() const {return "value.y";}
};
class ForceInfo;
class PmeIO;
class PmePreComputation;
class PmePostComputation;
class SyncStreamPreComputation;
class SyncStreamPostComputation;
HipContext& cu;
ForceInfo* info;
bool hasInitializedFFT;
HipArray charges;
HipArray sigmaEpsilon;
HipArray exceptionParams;
HipArray exclusionAtoms;
HipArray exclusionParams;
HipArray baseParticleParams;
HipArray baseExceptionParams;
HipArray particleParamOffsets;
HipArray exceptionParamOffsets;
HipArray particleOffsetIndices;
HipArray exceptionOffsetIndices;
HipArray globalParams;
HipArray cosSinSums;
HipArray pmeGrid1;
HipArray pmeGrid2;
HipArray pmeBsplineModuliX;
HipArray pmeBsplineModuliY;
HipArray pmeBsplineModuliZ;
HipArray pmeDispersionBsplineModuliX;
HipArray pmeDispersionBsplineModuliY;
HipArray pmeDispersionBsplineModuliZ;
HipArray pmeAtomGridIndex;
HipArray pmeEnergyBuffer;
HipSort* sort;
Kernel cpuPme;
PmeIO* pmeio;
hipStream_t pmeStream;
hipEvent_t pmeSyncEvent, paramsSyncEvent;
HipFFT3D* fft;
HipFFT3D* dispersionFft;
hipFunction_t computeParamsKernel, computeExclusionParamsKernel;
hipFunction_t ewaldSumsKernel;
hipFunction_t ewaldForcesKernel;
hipFunction_t pmeGridIndexKernel;
hipFunction_t pmeDispersionGridIndexKernel;
hipFunction_t pmeSpreadChargeKernel;
hipFunction_t pmeDispersionSpreadChargeKernel;
hipFunction_t pmeFinishSpreadChargeKernel;
hipFunction_t pmeDispersionFinishSpreadChargeKernel;
hipFunction_t pmeEvalEnergyKernel;
hipFunction_t pmeEvalDispersionEnergyKernel;
hipFunction_t pmeConvolutionKernel;
hipFunction_t pmeDispersionConvolutionKernel;
hipFunction_t pmeInterpolateForceKernel;
hipFunction_t pmeInterpolateDispersionForceKernel;
std::vector<std::pair<int, int> > exceptionAtoms;
std::vector<std::string> paramNames;
std::vector<double> paramValues;
double ewaldSelfEnergy, dispersionCoefficient, alpha, dispersionAlpha;
int interpolateForceThreads;
int gridSizeX, gridSizeY, gridSizeZ;
int dispersionGridSizeX, dispersionGridSizeY, dispersionGridSizeZ;
bool hasCoulomb, hasLJ, usePmeStream, doLJPME, usePosqCharges, recomputeParams, hasOffsets;
NonbondedMethod nonbondedMethod;
static const int PmeOrder = 5;
};
/**
* This kernel is invoked by CustomCVForce to calculate the forces acting on the system and the energy of the system.
*/
class HipCalcCustomCVForceKernel : public CommonCalcCustomCVForceKernel {
public:
HipCalcCustomCVForceKernel(std::string name, const Platform& platform, ComputeContext& cc) : CommonCalcCustomCVForceKernel(name, platform, cc) {
}
ComputeContext& getInnerComputeContext(ContextImpl& innerContext) {
return *reinterpret_cast<HipPlatform::PlatformData*>(innerContext.getPlatformData())->contexts[0];
}
};
/**
* This kernel is invoked by ATMForce to calculate the forces acting on the system and the energy of the system.
*/
class HipCalcATMForceKernel : public CommonCalcATMForceKernel {
public:
HipCalcATMForceKernel(std::string name, const Platform& platform, ComputeContext& cc) : CommonCalcATMForceKernel(name, platform, cc) {
}
ComputeContext& getInnerComputeContext(ContextImpl& innerContext) {
return *reinterpret_cast<HipPlatform::PlatformData*>(innerContext.getPlatformData())->contexts[0];
}
};
} // namespace OpenMM
#endif /*OPENMM_HIPKERNELS_H_*/
#ifndef OPENMM_HIPNONBONDEDUTILITIES_H_
#define OPENMM_HIPNONBONDEDUTILITIES_H_
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2009-2023 Stanford University and the Authors. *
* Portions copyright (c) 2020-2023 Advanced Micro Devices, Inc. *
* Authors: Peter Eastman, Nicholas Curtis *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "openmm/System.h"
#include "HipArray.h"
#include "HipExpressionUtilities.h"
#include "openmm/common/NonbondedUtilities.h"
#include <hip/hip_runtime.h>
#include <sstream>
#include <string>
#include <vector>
namespace OpenMM {
class HipContext;
class HipSort;
/**
* This class provides a generic interface for calculating nonbonded interactions. It does this in two
* ways. First, it can be used to create kernels that evaluate nonbonded interactions. Clients
* only need to provide the code for evaluating a single interaction and the list of parameters it depends on.
* A complete kernel is then synthesized using an appropriate algorithm to evaluate all interactions on all
* atoms.
*
* Second, this class itself creates and invokes a single "default" interaction kernel, allowing several
* different forces to be evaluated at once for greater efficiency. Call addInteraction() and addParameter()
* to add interactions to this default kernel.
*
* During each force or energy evaluation, the following sequence of steps takes place:
*
* 1. Data structures (e.g. neighbor lists) are calculated to allow nonbonded interactions to be evaluated
* quickly.
*
* 2. calcForcesAndEnergy() is called on each ForceImpl in the System.
*
* 3. Finally, the default interaction kernel is invoked to calculate all interactions that were added
* to it.
*
* This sequence means that the default interaction kernel may depend on quantities that were calculated
* by ForceImpls during calcForcesAndEnergy().
*/
class OPENMM_EXPORT_COMMON HipNonbondedUtilities : public NonbondedUtilities {
public:
class ParameterInfo;
HipNonbondedUtilities(HipContext& context);
~HipNonbondedUtilities();
/**
* Add a nonbonded interaction to be evaluated by the default interaction kernel.
*
* @param usesCutoff specifies whether a cutoff should be applied to this interaction
* @param usesPeriodic specifies whether periodic boundary conditions should be applied to this interaction
* @param usesExclusions specifies whether this interaction uses exclusions. If this is true, it must have identical exclusions to every other interaction.
* @param cutoffDistance the cutoff distance for this interaction (ignored if usesCutoff is false)
* @param exclusionList for each atom, specifies the list of other atoms whose interactions should be excluded
* @param kernel the code to evaluate the interaction
* @param forceGroup the force group in which the interaction should be calculated
* @param usesNeighborList specifies whether a neighbor list should be used to optimize this interaction. This should
* be viewed as only a suggestion. Even when it is false, a neighbor list may be used anyway.
*/
void addInteraction(bool usesCutoff, bool usesPeriodic, bool usesExclusions, double cutoffDistance, const std::vector<std::vector<int> >& exclusionList, const std::string& kernel, int forceGroup, bool usesNeighborList = true);
/**
* Add a nonbonded interaction to be evaluated by the default interaction kernel.
*
* @param usesCutoff specifies whether a cutoff should be applied to this interaction
* @param usesPeriodic specifies whether periodic boundary conditions should be applied to this interaction
* @param usesExclusions specifies whether this interaction uses exclusions. If this is true, it must have identical exclusions to every other interaction.
* @param cutoffDistance the cutoff distance for this interaction (ignored if usesCutoff is false)
* @param exclusionList for each atom, specifies the list of other atoms whose interactions should be excluded
* @param kernel the code to evaluate the interaction
* @param forceGroup the force group in which the interaction should be calculated
* @param usesNeighborList specifies whether a neighbor list should be used to optimize this interaction. This should
* be viewed as only a suggestion. Even when it is false, a neighbor list may be used anyway.
* @param supportsPairList specifies whether this interaction can work with a neighbor list that uses a separate pair list
*/
void addInteraction(bool usesCutoff, bool usesPeriodic, bool usesExclusions, double cutoffDistance, const std::vector<std::vector<int> >& exclusionList, const std::string& kernel, int forceGroup, bool usesNeighborList, bool supportsPairList);
/**
* Add a per-atom parameter that the default interaction kernel may depend on.
*/
void addParameter(ComputeParameterInfo parameter);
/**
* Add a per-atom parameter that the default interaction kernel may depend on.
*
* @deprecated Use the version that takes a ComputeParameterInfo instead.
*/
void addParameter(const ParameterInfo& parameter);
/**
* Add an array (other than a per-atom parameter) that should be passed as an argument to the default interaction kernel.
*/
void addArgument(ComputeParameterInfo parameter);
/**
* Add an array (other than a per-atom parameter) that should be passed as an argument to the default interaction kernel.
*
* @deprecated Use the version that takes a ComputeParameterInfo instead.
*/
void addArgument(const ParameterInfo& parameter);
/**
* Register that the interaction kernel will be computing the derivative of the potential energy
* with respect to a parameter.
*
* @param param the name of the parameter
* @return the variable that will be used to accumulate the derivative. Any code you pass to addInteraction() should
* add its contributions to this variable.
*/
std::string addEnergyParameterDerivative(const std::string& param);
/**
* Specify the list of exclusions that an interaction outside the default kernel will depend on.
*
* @param exclusionList for each atom, specifies the list of other atoms whose interactions should be excluded
*/
void requestExclusions(const std::vector<std::vector<int> >& exclusionList);
/**
* Initialize this object in preparation for a simulation.
*/
void initialize(const System& system);
/**
* Get the number of force buffers required for nonbonded forces.
*/
int getNumForceBuffers() const {
return 0;
}
/**
* Get the number of energy buffers required for nonbonded forces.
*/
int getNumEnergyBuffers() {
return numForceThreadBlocks*forceThreadBlockSize;
}
/**
* Get whether a cutoff is being used.
*/
bool getUseCutoff() {
return useCutoff;
}
/**
* Get whether periodic boundary conditions are being used.
*/
bool getUsePeriodic() {
return usePeriodic;
}
/**
* Get the number of work groups used for computing nonbonded forces.
*/
int getNumForceThreadBlocks() {
return numForceThreadBlocks;
}
/**
* Get the size of each work group used for computing nonbonded forces.
*/
int getForceThreadBlockSize() {
return forceThreadBlockSize;
}
/**
* Get the maximum cutoff distance used by any force group.
*/
double getMaxCutoffDistance();
/**
* Given a nonbonded cutoff, get the padded cutoff distance used in computing
* the neighbor list.
*/
double padCutoff(double cutoff);
/**
* Prepare to compute interactions. This updates the neighbor list.
*/
void prepareInteractions(int forceGroups);
/**
* Compute the nonbonded interactions.
*
* @param forceGroups the flags specifying which force groups to include
* @param includeForces whether to compute forces
* @param includeEnergy whether to compute the potential energy
*/
void computeInteractions(int forceGroups, bool includeForces, bool includeEnergy);
/**
* Check to see if the neighbor list arrays are large enough, and make them bigger if necessary.
*
* @return true if the neighbor list needed to be enlarged.
*/
bool updateNeighborListSize();
/**
* Get the array containing the center of each atom block.
*/
HipArray& getBlockCenters() {
return blockCenter;
}
/**
* Get the array containing the dimensions of each atom block.
*/
HipArray& getBlockBoundingBoxes() {
return blockBoundingBox;
}
/**
* Get the array whose first element contains the number of tiles with interactions.
*/
HipArray& getInteractionCount() {
return interactionCount;
}
/**
* Get the array containing tiles with interactions.
*/
HipArray& getInteractingTiles() {
return interactingTiles;
}
/**
* Get the array containing the atoms in each tile with interactions.
*/
HipArray& getInteractingAtoms() {
return interactingAtoms;
}
/**
* Get the array containing single pairs in the neighbor list.
*/
HipArray& getSinglePairs() {
return singlePairs;
}
/**
* Get the array containing exclusion flags.
*/
HipArray& getExclusions() {
return exclusions;
}
/**
* Get the array containing tiles with exclusions.
*/
HipArray& getExclusionTiles() {
return exclusionTiles;
}
/**
* Get the array containing the index into the exclusion array for each tile.
*/
HipArray& getExclusionIndices() {
return exclusionIndices;
}
/**
* Get the array listing where the exclusion data starts for each row.
*/
HipArray& getExclusionRowIndices() {
return exclusionRowIndices;
}
/**
* Get the array containing a flag for whether the neighbor list was rebuilt
* on the most recent call to prepareInteractions().
*/
HipArray& getRebuildNeighborList() {
return rebuildNeighborList;
}
/**
* Get the index of the first tile this context is responsible for processing.
*/
int getStartTileIndex() const {
return startTileIndex;
}
/**
* Get the total number of tiles this context is responsible for processing.
*/
int getNumTiles() const {
return numTiles;
}
/**
* Set whether to add padding to the cutoff distance when building the neighbor list.
* This increases the size of the neighbor list (and thus the cost of computing interactions),
* but also means we don't need to rebuild it every time step. The default value is true,
* since usually this improves performance. For very expensive interactions, however,
* it may be better to set this to false.
*/
void setUsePadding(bool padding);
/**
* Set the range of atom blocks and tiles that should be processed by this context.
*/
void setAtomBlockRange(double startFraction, double endFraction);
/**
* Create a Kernel for evaluating a nonbonded interaction. Cutoffs and periodic boundary conditions
* are assumed to be the same as those for the default interaction Kernel, since this kernel will use
* the same neighbor list.
*
* @param source the source code for evaluating the force and energy
* @param params the per-atom parameters this kernel may depend on
* @param arguments arrays (other than per-atom parameters) that should be passed as arguments to the kernel
* @param useExclusions specifies whether exclusions are applied to this interaction
* @param isSymmetric specifies whether the interaction is symmetric
* @param groups the set of force groups this kernel is for
* @param includeForces whether this kernel should compute forces
* @param includeEnergy whether this kernel should compute potential energy
*/
hipFunction_t createInteractionKernel(const std::string& source, std::vector<ParameterInfo>& params, std::vector<ParameterInfo>& arguments, bool useExclusions, bool isSymmetric, int groups, bool includeForces, bool includeEnergy);
/**
* Create the set of kernels that will be needed for a particular combination of force groups.
*
* @param groups the set of force groups
*/
void createKernelsForGroups(int groups);
/**
* Set the source code for the main kernel. This defaults to the content of nonbonded.hip. It only needs to be
* changed in very unusual circumstances.
*/
void setKernelSource(const std::string& source);
private:
class KernelSet;
class BlockSortTrait;
HipContext& context;
std::map<int, KernelSet> groupKernels;
HipArray exclusionTiles;
HipArray exclusions;
HipArray exclusionIndices;
HipArray exclusionRowIndices;
HipArray interactingTiles;
HipArray interactingAtoms;
HipArray interactionCount;
HipArray singlePairs;
HipArray singlePairCount;
HipArray blockCenter;
HipArray blockBoundingBox;
HipArray sortedBlocks;
HipArray sortedBlockCenter;
HipArray sortedBlockBoundingBox;
HipArray blockSizeRange;
HipArray largeBlockCenter;
HipArray largeBlockBoundingBox;
HipArray oldPositions;
HipArray rebuildNeighborList;
HipSort* blockSorter;
hipEvent_t downloadCountEvent;
unsigned int* pinnedCountBuffer;
std::vector<void*> forceArgs, findBlockBoundsArgs, computeSortKeysArgs, sortBoxDataArgs, findInteractingBlocksArgs, copyInteractionCountsArgs;
std::vector<std::vector<int> > atomExclusions;
std::vector<ParameterInfo> parameters;
std::vector<ParameterInfo> arguments;
std::vector<std::string> energyParameterDerivatives;
std::map<int, double> groupCutoff;
std::map<int, std::string> groupKernelSource;
double lastCutoff;
bool useCutoff, usePeriodic, anyExclusions, usePadding, useNeighborList, forceRebuildNeighborList, canUsePairList, useLargeBlocks;
int startTileIndex, startBlockIndex, numBlocks, numTilesInBatch, maxExclusions;
int numForceThreadBlocks, forceThreadBlockSize, findInteractingBlocksThreadBlockSize, numAtoms, groupFlags;
unsigned int maxTiles, maxSinglePairs, tilesAfterReorder;
long long numTiles;
std::string kernelSource;
};
/**
* This class stores the kernels to execute for a set of force groups.
*/
class HipNonbondedUtilities::KernelSet {
public:
bool hasForces;
double cutoffDistance;
std::string source;
hipFunction_t forceKernel, energyKernel, forceEnergyKernel;
hipFunction_t findBlockBoundsKernel;
hipFunction_t computeSortKeysKernel;
hipFunction_t sortBoxDataKernel;
hipFunction_t findInteractingBlocksKernel;
hipFunction_t copyInteractionCountsKernel;
};
/**
* This class stores information about a per-atom parameter that may be used in a nonbonded kernel.
*/
class HipNonbondedUtilities::ParameterInfo {
public:
/**
* Create a ParameterInfo object.
*
* @param name the name of the parameter
* @param type the data type of the parameter's components
* @param numComponents the number of components in the parameter
* @param size the size of the parameter in bytes
* @param memory the memory containing the parameter values
* @param constant whether the memory should be marked as constant
*/
ParameterInfo(const std::string& name, const std::string& componentType, int numComponents, int size, hipDeviceptr_t memory, bool constant=true) :
name(name), componentType(componentType), numComponents(numComponents), size(size), memory(memory), constant(constant) {
if (numComponents == 1)
type = componentType;
else {
std::stringstream s;
s << componentType << numComponents;
type = s.str();
}
}
const std::string& getName() const {
return name;
}
const std::string& getComponentType() const {
return componentType;
}
const std::string& getType() const {
return type;
}
int getNumComponents() const {
return numComponents;
}
int getSize() const {
return size;
}
hipDeviceptr_t& getMemory() {
return memory;
}
bool isConstant() const {
return constant;
}
private:
std::string name;
std::string componentType;
std::string type;
int size, numComponents;
hipDeviceptr_t memory;
bool constant;
};
} // namespace OpenMM
#endif /*OPENMM_HIPNONBONDEDUTILITIES_H_*/
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment