Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
66bc28f5
Commit
66bc28f5
authored
May 30, 2017
by
peastman
Committed by
GitHub
May 30, 2017
Browse files
Merge pull request #1826 from peastman/optimizeintegrator
CustomIntegrator avoids unnecessary force/energy computations
parents
fb607c7f
6a0e1bd5
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
62 additions
and
29 deletions
+62
-29
openmmapi/src/CustomIntegratorUtilities.cpp
openmmapi/src/CustomIntegratorUtilities.cpp
+8
-10
platforms/cuda/include/CudaKernels.h
platforms/cuda/include/CudaKernels.h
+1
-0
platforms/cuda/src/CudaKernels.cpp
platforms/cuda/src/CudaKernels.cpp
+18
-7
platforms/opencl/include/OpenCLKernels.h
platforms/opencl/include/OpenCLKernels.h
+1
-0
platforms/opencl/src/OpenCLKernels.cpp
platforms/opencl/src/OpenCLKernels.cpp
+16
-6
platforms/reference/src/SimTKReference/ReferenceCustomDynamics.cpp
.../reference/src/SimTKReference/ReferenceCustomDynamics.cpp
+18
-6
No files found.
openmmapi/src/CustomIntegratorUtilities.cpp
View file @
66bc28f5
...
...
@@ -37,6 +37,7 @@
#include <algorithm>
#include <set>
#include <sstream>
#include <utility>
using
namespace
OpenMM
;
using
namespace
std
;
...
...
@@ -250,26 +251,23 @@ void CustomIntegratorUtilities::enumeratePaths(int firstStep, vector<int> steps,
void
CustomIntegratorUtilities
::
analyzeForceComputationsForPath
(
vector
<
int
>&
steps
,
const
vector
<
bool
>&
needsForces
,
const
vector
<
bool
>&
needsEnergy
,
const
vector
<
bool
>&
invalidatesForces
,
const
vector
<
int
>&
forceGroup
,
vector
<
bool
>&
computeBoth
)
{
vector
<
int
>
candidatePoints
;
int
currentGroup
=
-
1
;
vector
<
pair
<
int
,
int
>
>
candidatePoints
;
for
(
int
step
:
steps
)
{
if
(
invalidatesForces
[
step
]
||
((
needsForces
[
step
]
||
needsEnergy
[
step
])
&&
forceGroup
[
step
]
!=
currentGroup
))
{
// Forces and energies are invalidated at this step, or it changes to a different force group,
// so anything from this point on won't affect what we do at earlier steps.
if
(
invalidatesForces
[
step
])
{
// Forces and energies are invalidated at this step, so anything from this point on won't affect what we do at earlier steps.
candidatePoints
.
clear
();
}
if
(
needsForces
[
step
]
||
needsEnergy
[
step
])
{
// See if this step affects what we do at earlier points.
for
(
int
candidate
:
candidatePoints
)
if
((
needsForces
[
candidate
]
&&
needsEnergy
[
step
])
||
(
needsEnergy
[
candidate
]
&&
needsForces
[
step
]))
computeBoth
[
candidate
]
=
true
;
for
(
auto
candidate
:
candidatePoints
)
if
(
candidate
.
second
==
forceGroup
[
step
]
&&
((
needsForces
[
candidate
.
first
]
&&
needsEnergy
[
step
])
||
(
needsEnergy
[
candidate
.
first
]
&&
needsForces
[
step
]))
)
computeBoth
[
candidate
.
first
]
=
true
;
// Add this to the list of candidates that might be affected by later steps.
candidatePoints
.
push_back
(
step
);
currentGroup
=
forceGroup
[
step
];
candidatePoints
.
push_back
(
make_pair
(
step
,
forceGroup
[
step
]));
}
}
}
...
...
platforms/cuda/include/CudaKernels.h
View file @
66bc28f5
...
...
@@ -1507,6 +1507,7 @@ private:
CudaArray
*
randomSeed
;
CudaArray
*
perDofEnergyParamDerivs
;
std
::
vector
<
CudaArray
*>
tabulatedFunctions
;
std
::
map
<
int
,
double
>
savedEnergy
;
std
::
map
<
int
,
CudaArray
*>
savedForces
;
std
::
set
<
int
>
validSavedForces
;
CudaParameterSet
*
perDofValues
;
...
...
platforms/cuda/src/CudaKernels.cpp
View file @
66bc28f5
...
...
@@ -7594,6 +7594,8 @@ void CudaIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegrat
CudaIntegrationUtilities& integration = cu.getIntegrationUtilities();
int numAtoms = cu.getNumAtoms();
int numSteps = integrator.getNumComputations();
if (!forcesAreValid)
savedEnergy.clear();
// Loop over computation steps in the integrator and execute them.
...
...
@@ -7602,8 +7604,11 @@ void CudaIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegrat
CUdeviceptr posCorrection = (cu.getUseMixedPrecision() ? cu.getPosqCorrection().getDevicePointer() : 0);
for (int step = 0; step < numSteps; ) {
int nextStep = step+1;
int forceGroups = forceGroupFlags[step];
int lastForceGroups = context.getLastForceGroups();
if ((needsForces[step] || needsEnergy[step]) && (!forcesAreValid || lastForceGroups != forceGroupFlags[step])) {
bool haveForces = (!needsForces[step] || (forcesAreValid && lastForceGroups == forceGroups));
bool haveEnergy = (!needsEnergy[step] || savedEnergy.find(forceGroups) != savedEnergy.end());
if (!haveForces || !haveEnergy) {
if (forcesAreValid) {
if (savedForces.find(lastForceGroups) != savedForces.end() && validSavedForces.find(lastForceGroups) == validSavedForces.end()) {
// The forces are still valid. We just need a different force group right now. Save the old
...
...
@@ -7621,16 +7626,16 @@ void CudaIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegrat
bool computeForce = (needsForces[step] || computeBothForceAndEnergy[step]);
bool computeEnergy = (needsEnergy[step] || computeBothForceAndEnergy[step]);
if (!computeEnergy && validSavedForces.find(forceGroup
Flags[step]
) != validSavedForces.end()) {
if (!computeEnergy && validSavedForces.find(forceGroup
s
) != validSavedForces.end()) {
// We can just restore the forces we saved earlier.
savedForces[forceGroup
Flags[step]
]->copyTo(cu.getForce());
context.getLastForceGroups() = forceGroup
Flags[step]
;
savedForces[forceGroup
s
]->copyTo(cu.getForce());
context.getLastForceGroups() = forceGroup
s
;
}
else {
recordChangedParameters(context);
energy = context.calcForcesAndEnergy(computeForce, computeEnergy, forceGroup
Flags[step]
);
energyFloat = (float)
energy;
energy = context.calcForcesAndEnergy(computeForce, computeEnergy, forceGroup
s
);
savedEnergy[forceGroups] =
energy;
if (needsEnergyParamDerivs) {
context.getEnergyParameterDerivatives(energyParamDerivs);
if (perDofEnergyParamDerivNames.size() > 0) {
...
...
@@ -7649,6 +7654,10 @@ void CudaIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegrat
}
forcesAreValid = true;
}
if (needsEnergy[step]) {
energy = savedEnergy[forceGroups];
energyFloat = (float) energy;
}
if (needsGlobals[step] && !deviceGlobalsAreCurrent) {
// Upload the global values to the device.
...
...
@@ -7725,8 +7734,10 @@ void CudaIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegrat
if (blockEnd[step] != -1)
nextStep = blockEnd[step]; // Return to the start of a while block.
}
if (invalidatesForces[step])
if (invalidatesForces[step])
{
forcesAreValid = false;
savedEnergy.clear();
}
step = nextStep;
}
recordChangedParameters(context);
...
...
platforms/opencl/include/OpenCLKernels.h
View file @
66bc28f5
...
...
@@ -1494,6 +1494,7 @@ private:
OpenCLArray
*
randomSeed
;
OpenCLArray
*
perDofEnergyParamDerivs
;
std
::
vector
<
OpenCLArray
*>
tabulatedFunctions
;
std
::
map
<
int
,
double
>
savedEnergy
;
std
::
map
<
int
,
OpenCLArray
*>
savedForces
;
std
::
set
<
int
>
validSavedForces
;
OpenCLParameterSet
*
perDofValues
;
...
...
platforms/opencl/src/OpenCLKernels.cpp
View file @
66bc28f5
...
...
@@ -7937,13 +7937,18 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
OpenCLIntegrationUtilities& integration = cl.getIntegrationUtilities();
int numAtoms = cl.getNumAtoms();
int numSteps = integrator.getNumComputations();
if (!forcesAreValid)
savedEnergy.clear();
// Loop over computation steps in the integrator and execute them.
for (int step = 0; step < numSteps; ) {
int nextStep = step+1;
int forceGroups = forceGroupFlags[step];
int lastForceGroups = context.getLastForceGroups();
if ((needsForces[step] || needsEnergy[step]) && (!forcesAreValid || lastForceGroups != forceGroupFlags[step])) {
bool haveForces = (!needsForces[step] || (forcesAreValid && lastForceGroups == forceGroups));
bool haveEnergy = (!needsEnergy[step] || savedEnergy.find(forceGroups) != savedEnergy.end());
if (!haveForces || !haveEnergy) {
if (forcesAreValid) {
if (savedForces.find(lastForceGroups) != savedForces.end() && validSavedForces.find(lastForceGroups) == validSavedForces.end()) {
// The forces are still valid. We just need a different force group right now. Save the old
...
...
@@ -7961,15 +7966,16 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
bool computeForce = (needsForces[step] || computeBothForceAndEnergy[step]);
bool computeEnergy = (needsEnergy[step] || computeBothForceAndEnergy[step]);
if (!computeEnergy && validSavedForces.find(forceGroup
Flags[step]
) != validSavedForces.end()) {
if (!computeEnergy && validSavedForces.find(forceGroup
s
) != validSavedForces.end()) {
// We can just restore the forces we saved earlier.
savedForces[forceGroup
Flags[step]
]->copyTo(cl.getForce());
context.getLastForceGroups() = forceGroup
Flags[step]
;
savedForces[forceGroup
s
]->copyTo(cl.getForce());
context.getLastForceGroups() = forceGroup
s
;
}
else {
recordChangedParameters(context);
energy = context.calcForcesAndEnergy(computeForce, computeEnergy, forceGroupFlags[step]);
energy = context.calcForcesAndEnergy(computeForce, computeEnergy, forceGroups);
savedEnergy[forceGroups] = energy;
if (needsEnergyParamDerivs) {
context.getEnergyParameterDerivatives(energyParamDerivs);
if (perDofEnergyParamDerivNames.size() > 0) {
...
...
@@ -7988,6 +7994,8 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
forcesAreValid = true;
}
}
if (needsEnergy[step])
energy = savedEnergy[forceGroups];
if (needsGlobals[step] && !deviceGlobalsAreCurrent) {
// Upload the global values to the device.
...
...
@@ -8067,8 +8075,10 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
if (blockEnd[step] != -1)
nextStep = blockEnd[step]; // Return to the start of a while block.
}
if (invalidatesForces[step])
if (invalidatesForces[step])
{
forcesAreValid = false;
savedEnergy.clear();
}
step = nextStep;
}
recordChangedParameters(context);
...
...
platforms/reference/src/SimTKReference/ReferenceCustomDynamics.cpp
View file @
66bc28f5
/* Portions copyright (c) 2011-201
6
Stanford University and Simbios.
/* Portions copyright (c) 2011-201
7
Stanford University and Simbios.
* Contributors: Peter Eastman
*
* Permission is hereby granted, free of charge, to any person obtaining
...
...
@@ -219,19 +219,26 @@ void ReferenceCustomDynamics::update(ContextImpl& context, int numberOfAtoms, ve
for
(
auto
&
global
:
globals
)
expressionSet
.
setVariable
(
expressionSet
.
getVariableIndex
(
global
.
first
),
global
.
second
);
oldPos
=
atomCoordinates
;
map
<
int
,
double
>
groupEnergy
;
map
<
int
,
vector
<
Vec3
>
>
groupForces
;
if
(
forcesAreValid
)
groupForces
[
context
.
getLastForceGroups
()]
=
forces
;
// Loop over steps and execute them.
for
(
int
step
=
0
;
step
<
numSteps
;
)
{
if
((
needsForces
[
step
]
||
needsEnergy
[
step
])
&&
(
!
forcesAreValid
||
context
.
getLastForceGroups
()
!=
forceGroupFlags
[
step
]))
{
int
flags
=
forceGroupFlags
[
step
];
if
((
needsForces
[
step
]
&&
groupForces
.
find
(
flags
)
==
groupForces
.
end
())
||
(
needsEnergy
[
step
]
&&
groupEnergy
.
find
(
flags
)
==
groupEnergy
.
end
()))
{
// Recompute forces and/or energy.
bool
computeForce
=
needsForces
[
step
]
||
computeBothForceAndEnergy
[
step
];
bool
computeEnergy
=
needsEnergy
[
step
]
||
computeBothForceAndEnergy
[
step
];
recordChangedParameters
(
context
,
globals
);
double
e
=
context
.
calcForcesAndEnergy
(
computeForce
,
computeEnergy
,
forceGroupFlags
[
step
]);
if
(
computeForce
)
groupForces
[
flags
]
=
forces
;
if
(
computeEnergy
)
{
energy
=
e
;
groupEnergy
[
flags
]
=
e
;
context
.
getEnergyParameterDerivatives
(
energyParamDerivs
);
}
forcesAreValid
=
true
;
...
...
@@ -239,6 +246,8 @@ void ReferenceCustomDynamics::update(ContextImpl& context, int numberOfAtoms, ve
// Execute the step.
energy
=
(
needsEnergy
[
step
]
?
groupEnergy
[
flags
]
:
0
);
vector
<
Vec3
>&
stepForces
=
(
needsForces
[
step
]
?
groupForces
[
flags
]
:
forces
);
int
nextStep
=
step
+
1
;
switch
(
stepType
[
step
])
{
case
CustomIntegrator
::
ComputeGlobal
:
{
...
...
@@ -262,11 +271,11 @@ void ReferenceCustomDynamics::update(ContextImpl& context, int numberOfAtoms, ve
}
if
(
results
==
NULL
)
throw
OpenMMException
(
"Illegal per-DOF output variable: "
+
stepVariable
[
step
]);
computePerDof
(
numberOfAtoms
,
*
results
,
atomCoordinates
,
velocities
,
f
orces
,
masses
,
perDof
,
stepExpressions
[
step
][
0
]);
computePerDof
(
numberOfAtoms
,
*
results
,
atomCoordinates
,
velocities
,
stepF
orces
,
masses
,
perDof
,
stepExpressions
[
step
][
0
]);
break
;
}
case
CustomIntegrator
::
ComputeSum
:
{
computePerDof
(
numberOfAtoms
,
sumBuffer
,
atomCoordinates
,
velocities
,
f
orces
,
masses
,
perDof
,
stepExpressions
[
step
][
0
]);
computePerDof
(
numberOfAtoms
,
sumBuffer
,
atomCoordinates
,
velocities
,
stepF
orces
,
masses
,
perDof
,
stepExpressions
[
step
][
0
]);
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
numberOfAtoms
;
j
++
)
if
(
masses
[
j
]
!=
0.0
)
...
...
@@ -308,8 +317,11 @@ void ReferenceCustomDynamics::update(ContextImpl& context, int numberOfAtoms, ve
break
;
}
}
if
(
invalidatesForces
[
step
])
if
(
invalidatesForces
[
step
])
{
forcesAreValid
=
false
;
groupForces
.
clear
();
groupEnergy
.
clear
();
}
step
=
nextStep
;
}
ReferenceVirtualSites
::
computePositions
(
context
.
getSystem
(),
atomCoordinates
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment