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
9ddded35
"platforms/cpu/include/CpuBondForce.h" did not exist on "b1be68d873e649ab07ae6c65f017163066373123"
Commit
9ddded35
authored
Jul 17, 2015
by
peastman
Browse files
OpenCL CustomIntegrator supports if and while blocks
parent
506908ce
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
360 additions
and
291 deletions
+360
-291
platforms/cuda/tests/TestCudaCustomIntegrator.cpp
platforms/cuda/tests/TestCudaCustomIntegrator.cpp
+1
-1
platforms/opencl/include/OpenCLKernels.h
platforms/opencl/include/OpenCLKernels.h
+37
-11
platforms/opencl/src/OpenCLKernels.cpp
platforms/opencl/src/OpenCLKernels.cpp
+254
-268
platforms/opencl/src/kernels/customIntegrator.cl
platforms/opencl/src/kernels/customIntegrator.cl
+4
-4
platforms/opencl/src/kernels/customIntegratorGlobal.cl
platforms/opencl/src/kernels/customIntegratorGlobal.cl
+0
-4
platforms/opencl/src/kernels/customIntegratorPerDof.cl
platforms/opencl/src/kernels/customIntegratorPerDof.cl
+1
-2
platforms/opencl/tests/TestOpenCLCustomIntegrator.cpp
platforms/opencl/tests/TestOpenCLCustomIntegrator.cpp
+63
-1
No files found.
platforms/cuda/tests/TestCudaCustomIntegrator.cpp
View file @
9ddded35
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
platforms/opencl/include/OpenCLKernels.h
View file @
9ddded35
...
...
@@ -34,6 +34,9 @@
#include "OpenCLParameterSet.h"
#include "OpenCLSort.h"
#include "openmm/kernels.h"
#include "openmm/internal/CompiledExpressionSet.h"
#include "openmm/internal/CustomIntegratorUtilities.h"
#include "lepton/CompiledExpression.h"
#include "openmm/System.h"
namespace
OpenMM
{
...
...
@@ -1202,9 +1205,10 @@ private:
*/
class
OpenCLIntegrateCustomStepKernel
:
public
IntegrateCustomStepKernel
{
public:
enum
GlobalTargetType
{
DT
,
VARIABLE
,
PARAMETER
};
OpenCLIntegrateCustomStepKernel
(
std
::
string
name
,
const
Platform
&
platform
,
OpenCLContext
&
cl
)
:
IntegrateCustomStepKernel
(
name
,
platform
),
cl
(
cl
),
hasInitializedKernels
(
false
),
localValuesAreCurrent
(
false
),
globalValues
(
NULL
),
contextParameterValues
(
NULL
),
sumBuffer
(
NULL
),
potentialEnergy
(
NULL
),
kineticEnergy
(
NULL
),
uniformRandoms
(
NULL
),
randomSeed
(
NULL
),
perDofValues
(
NULL
)
{
hasInitializedKernels
(
false
),
localValuesAreCurrent
(
false
),
globalValues
(
NULL
),
sumBuffer
(
NULL
),
summedValue
(
NULL
),
uniformRandoms
(
NULL
),
randomSeed
(
NULL
),
perDofValues
(
NULL
)
{
}
~
OpenCLIntegrateCustomStepKernel
();
/**
...
...
@@ -1268,20 +1272,21 @@ public:
void
setPerDofVariable
(
ContextImpl
&
context
,
int
variable
,
const
std
::
vector
<
Vec3
>&
values
);
private:
class
ReorderListener
;
std
::
string
createGlobalComputation
(
const
std
::
string
&
variable
,
const
Lepton
::
ParsedExpression
&
expr
,
CustomIntegrator
&
integrator
,
const
std
::
string
&
energyName
)
;
class
GlobalTarget
;
std
::
string
createPerDofComputation
(
const
std
::
string
&
variable
,
const
Lepton
::
ParsedExpression
&
expr
,
int
component
,
CustomIntegrator
&
integrator
,
const
std
::
string
&
forceName
,
const
std
::
string
&
energyName
);
void
prepareForComputation
(
ContextImpl
&
context
,
CustomIntegrator
&
integrator
,
bool
&
forcesAreValid
);
void
recordGlobalValue
(
double
value
,
GlobalTarget
target
);
void
recordChangedParameters
(
ContextImpl
&
context
);
bool
evaluateCondition
(
int
step
);
OpenCLContext
&
cl
;
double
prevStepSize
,
energy
;
float
energyFloat
;
int
numGlobalVariables
;
bool
hasInitializedKernels
,
deviceValuesAreCurrent
,
modifiesParameters
,
keNeedsForce
;
bool
hasInitializedKernels
,
deviceValuesAreCurrent
,
deviceGlobalsAreCurrent
,
modifiesParameters
,
keNeedsForce
;
mutable
bool
localValuesAreCurrent
;
OpenCLArray
*
globalValues
;
OpenCLArray
*
contextParameterValues
;
OpenCLArray
*
sumBuffer
;
OpenCLArray
*
potentialEnergy
;
OpenCLArray
*
kineticEnergy
;
OpenCLArray
*
summedValue
;
OpenCLArray
*
uniformRandoms
;
OpenCLArray
*
randomSeed
;
std
::
map
<
int
,
OpenCLArray
*>
savedForces
;
...
...
@@ -1289,20 +1294,41 @@ private:
OpenCLParameterSet
*
perDofValues
;
mutable
std
::
vector
<
std
::
vector
<
cl_float
>
>
localPerDofValuesFloat
;
mutable
std
::
vector
<
std
::
vector
<
cl_double
>
>
localPerDofValuesDouble
;
std
::
vector
<
float
>
context
ValuesFloat
;
std
::
vector
<
double
>
context
ValuesDouble
;
std
::
vector
<
float
>
contextValu
es
;
std
::
vector
<
float
>
global
ValuesFloat
;
std
::
vector
<
double
>
global
ValuesDouble
;
std
::
vector
<
double
>
initialGlobalVariabl
es
;
std
::
vector
<
std
::
vector
<
cl
::
Kernel
>
>
kernels
;
cl
::
Kernel
randomKernel
,
kineticEnergyKernel
,
sumKineticEnergyKernel
;
std
::
vector
<
CustomIntegrator
::
ComputationType
>
stepType
;
std
::
vector
<
CustomIntegratorUtilities
::
Comparison
>
comparisons
;
std
::
vector
<
std
::
vector
<
Lepton
::
CompiledExpression
>
>
globalExpressions
;
CompiledExpressionSet
expressionSet
;
std
::
vector
<
bool
>
needsGlobals
;
std
::
vector
<
bool
>
needsForces
;
std
::
vector
<
bool
>
needsEnergy
;
std
::
vector
<
bool
>
computeBothForceAndEnergy
;
std
::
vector
<
bool
>
invalidatesForces
;
std
::
vector
<
bool
>
merged
;
std
::
vector
<
int
>
forceGroup
;
std
::
vector
<
int
>
forceGroupFlags
;
std
::
vector
<
int
>
blockEnd
;
std
::
vector
<
int
>
requiredGaussian
;
std
::
vector
<
int
>
requiredUniform
;
std
::
vector
<
int
>
stepEnergyVariableIndex
;
std
::
vector
<
int
>
globalVariableIndex
;
std
::
vector
<
int
>
parameterVariableIndex
;
int
gaussianVariableIndex
,
uniformVariableIndex
,
dtVariableIndex
;
std
::
vector
<
std
::
string
>
parameterNames
;
std
::
vector
<
GlobalTarget
>
stepTarget
;
};
class
OpenCLIntegrateCustomStepKernel
::
GlobalTarget
{
public:
OpenCLIntegrateCustomStepKernel
::
GlobalTargetType
type
;
int
variableIndex
;
GlobalTarget
()
{
}
GlobalTarget
(
OpenCLIntegrateCustomStepKernel
::
GlobalTargetType
type
,
int
variableIndex
)
:
type
(
type
),
variableIndex
(
variableIndex
)
{
}
};
/**
...
...
platforms/opencl/src/OpenCLKernels.cpp
View file @
9ddded35
...
...
@@ -5940,14 +5940,10 @@ private:
OpenCLIntegrateCustomStepKernel
::~
OpenCLIntegrateCustomStepKernel
()
{
if
(
globalValues
!=
NULL
)
delete
globalValues
;
if (contextParameterValues != NULL)
delete contextParameterValues;
if
(
sumBuffer
!=
NULL
)
delete
sumBuffer
;
if (potentialEnergy != NULL)
delete potentialEnergy;
if (kineticEnergy != NULL)
delete kineticEnergy;
if
(
summedValue
!=
NULL
)
delete
summedValue
;
if
(
uniformRandoms
!=
NULL
)
delete
uniformRandoms
;
if
(
randomSeed
!=
NULL
)
...
...
@@ -5963,46 +5959,14 @@ void OpenCLIntegrateCustomStepKernel::initialize(const System& system, const Cus
cl
.
getIntegrationUtilities
().
initRandomNumberGenerator
(
integrator
.
getRandomNumberSeed
());
numGlobalVariables
=
integrator
.
getNumGlobalVariables
();
int
elementSize
=
(
cl
.
getUseDoublePrecision
()
||
cl
.
getUseMixedPrecision
()
?
sizeof
(
double
)
:
sizeof
(
float
));
globalValues = new OpenCLArray(cl, max(1, numGlobalVariables), elementSize, "globalVariables");
sumBuffer
=
new
OpenCLArray
(
cl
,
((
3
*
system
.
getNumParticles
()
+
3
)
/
4
)
*
4
,
elementSize
,
"sumBuffer"
);
potentialEnergy = new OpenCLArray(cl, 1, cl.getEnergyBuffer().getElementSize(), "potentialEnergy");
kineticEnergy = new OpenCLArray(cl, 1, elementSize, "kineticEnergy");
summedValue
=
new
OpenCLArray
(
cl
,
1
,
elementSize
,
"summedValue"
);
perDofValues
=
new
OpenCLParameterSet
(
cl
,
integrator
.
getNumPerDofVariables
(),
3
*
system
.
getNumParticles
(),
"perDofVariables"
,
false
,
cl
.
getUseDoublePrecision
()
||
cl
.
getUseMixedPrecision
());
cl
.
addReorderListener
(
new
ReorderListener
(
cl
,
*
perDofValues
,
localPerDofValuesFloat
,
localPerDofValuesDouble
,
deviceValuesAreCurrent
));
prevStepSize
=
-
1.0
;
SimTKOpenMMUtilities
::
setRandomNumberSeed
(
integrator
.
getRandomNumberSeed
());
}
string OpenCLIntegrateCustomStepKernel::createGlobalComputation(const string& variable, const Lepton::ParsedExpression& expr, CustomIntegrator& integrator, const string& energyName) {
map<string, Lepton::ParsedExpression> expressions;
if (variable == "dt")
expressions["dt[0].y = "] = expr;
else {
for (int i = 0; i < integrator.getNumGlobalVariables(); i++)
if (variable == integrator.getGlobalVariableName(i))
expressions["globals["+cl.intToString(i)+"] = "] = expr;
for (int i = 0; i < (int) parameterNames.size(); i++)
if (variable == parameterNames[i]) {
expressions["params["+cl.intToString(i)+"] = "] = expr;
modifiesParameters = true;
}
}
if (expressions.size() == 0)
throw OpenMMException("Unknown global variable: "+variable);
map<string, string> variables;
variables["dt"] = "dt[0].y";
variables["uniform"] = "uniform";
variables["gaussian"] = "gaussian";
variables[energyName] = "energy";
for (int i = 0; i < integrator.getNumGlobalVariables(); i++)
variables[integrator.getGlobalVariableName(i)] = "globals["+cl.intToString(i)+"]";
for (int i = 0; i < (int) parameterNames.size(); i++)
variables[parameterNames[i]] = "params["+cl.intToString(i)+"]";
vector<const TabulatedFunction*> functions;
vector<pair<string, string> > functionNames;
return cl.getExpressionUtilities().createExpressions(expressions, variables, functions, functionNames, "temp");
}
string
OpenCLIntegrateCustomStepKernel
::
createPerDofComputation
(
const
string
&
variable
,
const
Lepton
::
ParsedExpression
&
expr
,
int
component
,
CustomIntegrator
&
integrator
,
const
string
&
forceName
,
const
string
&
energyName
)
{
const
string
suffixes
[]
=
{
".x"
,
".y"
,
".z"
};
string
suffix
=
suffixes
[
component
];
...
...
@@ -6031,11 +5995,11 @@ string OpenCLIntegrateCustomStepKernel::createPerDofComputation(const string& va
if
(
energyName
!=
""
)
variables
[
energyName
]
=
"energy"
;
for
(
int
i
=
0
;
i
<
integrator
.
getNumGlobalVariables
();
i
++
)
variables[integrator.getGlobalVariableName(i)] = "globals["+cl.intToString(
i
)+"]";
variables
[
integrator
.
getGlobalVariableName
(
i
)]
=
"globals["
+
cl
.
intToString
(
globalVariableIndex
[
i
]
)
+
"]"
;
for
(
int
i
=
0
;
i
<
integrator
.
getNumPerDofVariables
();
i
++
)
variables
[
integrator
.
getPerDofVariableName
(
i
)]
=
"perDof"
+
suffix
.
substr
(
1
)
+
perDofValues
->
getParameterSuffix
(
i
);
for
(
int
i
=
0
;
i
<
(
int
)
parameterNames
.
size
();
i
++
)
variables[parameterNames[i]] = "
param
s["+cl.intToString(
i
)+"]";
variables
[
parameterNames
[
i
]]
=
"
global
s["
+
cl
.
intToString
(
parameterVariableIndex
[
i
]
)
+
"]"
;
vector
<
const
TabulatedFunction
*>
functions
;
vector
<
pair
<
string
,
string
>
>
functionNames
;
string
tempType
=
(
cl
.
getSupportsDoublePrecision
()
?
"double"
:
"float"
);
...
...
@@ -6053,53 +6017,54 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
// Initialize various data structures.
const
map
<
string
,
double
>&
params
=
context
.
getParameters
();
if (useDouble) {
contextParameterValues = OpenCLArray::create<cl_double>(cl, max(1, (int) params.size()), "contextParameters");
contextValuesDouble.resize(contextParameterValues->getSize());
for (map<string, double>::const_iterator iter = params.begin(); iter != params.end(); ++iter) {
contextValuesDouble[parameterNames.size()] = iter->second;
for
(
map
<
string
,
double
>::
const_iterator
iter
=
params
.
begin
();
iter
!=
params
.
end
();
++
iter
)
parameterNames
.
push_back
(
iter
->
first
);
}
contextParameterValues->upload(contextValuesDouble);
}
else {
contextParameterValues = OpenCLArray::create<cl_float>(cl, max(1, (int) params.size()), "contextParameters");
contextValuesFloat.resize(contextParameterValues->getSize());
for (map<string, double>::const_iterator iter = params.begin(); iter != params.end(); ++iter) {
contextValuesFloat[parameterNames.size()] = (float) iter->second;
parameterNames.push_back(iter->first);
}
contextParameterValues->upload(contextValuesFloat);
}
kernels
.
resize
(
integrator
.
getNumComputations
());
requiredGaussian
.
resize
(
integrator
.
getNumComputations
(),
0
);
requiredUniform
.
resize
(
integrator
.
getNumComputations
(),
0
);
needs
Force
s.resize(numSteps, false);
needsEnergy
.resize(numSteps
, false
);
forceGroup
.resize(numSteps
, -2
);
invalidatesForces
.resize(numSteps
, false
);
needs
Global
s
.
resize
(
numSteps
,
false
);
globalExpressions
.
resize
(
numSteps
);
stepType
.
resize
(
numSteps
);
stepTarget
.
resize
(
numSteps
);
merged
.
resize
(
numSteps
,
false
);
modifiesParameters
=
false
;
map
<
string
,
string
>
defines
;
defines
[
"NUM_ATOMS"
]
=
cl
.
intToString
(
cl
.
getNumAtoms
());
defines
[
"WORK_GROUP_SIZE"
]
=
cl
.
intToString
(
OpenCLContext
::
ThreadBlockSize
);
// Build a list of all variables that affect the forces, so we can tell which
// steps invalidate them.
// Record information about all the computation steps.
set<string> affectsForce;
affectsForce.insert("x");
for (vector<ForceImpl*>::const_iterator iter = context.getForceImpls().begin(); iter != context.getForceImpls().end(); ++iter) {
const map<string, double> params = (*iter)->getDefaultParameters();
for (map<string, double>::const_iterator param = params.begin(); param != params.end(); ++param)
affectsForce.insert(param->first);
vector
<
string
>
variable
(
numSteps
);
vector
<
int
>
forceGroup
;
vector
<
vector
<
Lepton
::
ParsedExpression
>
>
expression
;
CustomIntegratorUtilities
::
analyzeComputations
(
context
,
integrator
,
expression
,
comparisons
,
blockEnd
,
invalidatesForces
,
needsForces
,
needsEnergy
,
computeBothForceAndEnergy
,
forceGroup
);
for
(
int
step
=
0
;
step
<
numSteps
;
step
++
)
{
string
expr
;
integrator
.
getComputationStep
(
step
,
stepType
[
step
],
variable
[
step
],
expr
);
if
(
stepType
[
step
]
==
CustomIntegrator
::
BeginWhileBlock
)
blockEnd
[
blockEnd
[
step
]]
=
step
;
// Record where to branch back to.
if
(
stepType
[
step
]
==
CustomIntegrator
::
ComputeGlobal
||
stepType
[
step
]
==
CustomIntegrator
::
BeginIfBlock
||
stepType
[
step
]
==
CustomIntegrator
::
BeginWhileBlock
)
for
(
int
i
=
0
;
i
<
(
int
)
expression
[
step
].
size
();
i
++
)
globalExpressions
[
step
].
push_back
(
expression
[
step
][
i
].
createCompiledExpression
());
}
for
(
int
step
=
0
;
step
<
numSteps
;
step
++
)
{
for
(
int
i
=
0
;
i
<
(
int
)
globalExpressions
[
step
].
size
();
i
++
)
expressionSet
.
registerExpression
(
globalExpressions
[
step
][
i
]);
}
// Record
information about all
the
c
omp
utation steps
.
// Record
the indices for variables in
the
C
omp
iledExpressionSet
.
stepType.resize(numSteps);
vector<string> variable(numSteps);
vector<Lepton::ParsedExpression> expression(numSteps);
gaussianVariableIndex
=
expressionSet
.
getVariableIndex
(
"gaussian"
);
uniformVariableIndex
=
expressionSet
.
getVariableIndex
(
"uniform"
);
dtVariableIndex
=
expressionSet
.
getVariableIndex
(
"dt"
);
for
(
int
i
=
0
;
i
<
integrator
.
getNumGlobalVariables
();
i
++
)
globalVariableIndex
.
push_back
(
expressionSet
.
getVariableIndex
(
integrator
.
getGlobalVariableName
(
i
)));
for
(
int
i
=
0
;
i
<
(
int
)
parameterNames
.
size
();
i
++
)
parameterVariableIndex
.
push_back
(
expressionSet
.
getVariableIndex
(
parameterNames
[
i
]));
// Record the variable names and flags for the force and energy in each step.
forceGroupFlags
.
resize
(
numSteps
,
-
1
);
vector
<
string
>
forceGroupName
;
vector
<
string
>
energyGroupName
;
for
(
int
i
=
0
;
i
<
32
;
i
++
)
{
...
...
@@ -6112,41 +6077,67 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
}
vector
<
string
>
forceName
(
numSteps
,
"f"
);
vector
<
string
>
energyName
(
numSteps
,
"energy"
);
stepEnergyVariableIndex
.
resize
(
numSteps
,
expressionSet
.
getVariableIndex
(
"energy"
));
for
(
int
step
=
0
;
step
<
numSteps
;
step
++
)
{
string expr;
integrator.getComputationStep(step, stepType[step], variable[step], expr);
if (expr.size() > 0) {
expression[step] = Lepton::Parser::parse(expr).optimize();
if (usesVariable(expression[step], "f")) {
needsForces[step] = true;
forceGroup[step] = -1;
if
(
needsForces
[
step
]
&&
forceGroup
[
step
]
>
-
1
)
forceName
[
step
]
=
forceGroupName
[
forceGroup
[
step
]];
if
(
needsEnergy
[
step
]
&&
forceGroup
[
step
]
>
-
1
)
{
energyName
[
step
]
=
energyGroupName
[
forceGroup
[
step
]];
stepEnergyVariableIndex
[
step
]
=
expressionSet
.
getVariableIndex
(
energyName
[
step
]);
}
if (usesVariable(expression[step], "energy")) {
needsEnergy[step] = true;
forceGroup[step] = -1;
if
(
forceGroup
[
step
]
>
-
1
)
forceGroupFlags
[
step
]
=
1
<<
forceGroup
[
step
];
if
(
forceGroupFlags
[
step
]
==
-
2
&&
step
>
0
)
forceGroupFlags
[
step
]
=
forceGroupFlags
[
step
-
1
];
if
(
forceGroupFlags
[
step
]
!=
-
2
&&
savedForces
.
find
(
forceGroupFlags
[
step
])
==
savedForces
.
end
())
savedForces
[
forceGroupFlags
[
step
]]
=
new
OpenCLArray
(
cl
,
cl
.
getForce
().
getSize
(),
cl
.
getForce
().
getElementSize
(),
"savedForces"
);
}
for (int i = 0; i < 32; i++) {
if (usesVariable(expression[step], forceGroupName[i])) {
if (forceGroup[step] != -2)
throw OpenMMException("A single computation step cannot depend on multiple force groups");
needsForces[step] = true;
forceGroup[step] = 1<<i;
forceName[step] = forceGroupName[i];
// Allocate space for storing global values, both on the host and the device.
globalValuesFloat
.
resize
(
expressionSet
.
getNumVariables
());
globalValuesDouble
.
resize
(
expressionSet
.
getNumVariables
());
int
elementSize
=
(
cl
.
getUseDoublePrecision
()
||
cl
.
getUseMixedPrecision
()
?
sizeof
(
double
)
:
sizeof
(
float
));
globalValues
=
new
OpenCLArray
(
cl
,
expressionSet
.
getNumVariables
(),
elementSize
,
"globalValues"
);
for
(
int
i
=
0
;
i
<
integrator
.
getNumGlobalVariables
();
i
++
)
{
globalValuesDouble
[
globalVariableIndex
[
i
]]
=
initialGlobalVariables
[
i
];
expressionSet
.
setVariable
(
globalVariableIndex
[
i
],
initialGlobalVariables
[
i
]);
}
for
(
int
i
=
0
;
i
<
(
int
)
parameterVariableIndex
.
size
();
i
++
)
{
double
value
=
context
.
getParameter
(
parameterNames
[
i
]);
globalValuesDouble
[
parameterVariableIndex
[
i
]]
=
value
;
expressionSet
.
setVariable
(
parameterVariableIndex
[
i
],
value
);
}
// Record information about the targets of steps that will be stored in global variables.
for
(
int
step
=
0
;
step
<
numSteps
;
step
++
)
{
if
(
stepType
[
step
]
==
CustomIntegrator
::
ComputeGlobal
||
stepType
[
step
]
==
CustomIntegrator
::
ComputeSum
)
{
if
(
variable
[
step
]
==
"dt"
)
stepTarget
[
step
].
type
=
DT
;
for
(
int
i
=
0
;
i
<
integrator
.
getNumGlobalVariables
();
i
++
)
if
(
variable
[
step
]
==
integrator
.
getGlobalVariableName
(
i
))
stepTarget
[
step
].
type
=
VARIABLE
;
for
(
int
i
=
0
;
i
<
(
int
)
parameterNames
.
size
();
i
++
)
if
(
variable
[
step
]
==
parameterNames
[
i
])
{
stepTarget
[
step
].
type
=
PARAMETER
;
modifiesParameters
=
true
;
}
if (usesVariable(expression[step], energyGroupName[i])) {
if (forceGroup[step] != -2)
throw OpenMMException("A single computation step cannot depend on multiple force groups");
needsEnergy[step] = true;
forceGroup[step] = 1<<i;
energyName[step] = energyGroupName[i];
stepTarget
[
step
].
variableIndex
=
expressionSet
.
getVariableIndex
(
variable
[
step
]);
}
}
// Identify which per-DOF steps are going to require global variables or context parameters.
for
(
int
step
=
0
;
step
<
numSteps
;
step
++
)
{
if
(
stepType
[
step
]
==
CustomIntegrator
::
ComputePerDof
||
stepType
[
step
]
==
CustomIntegrator
::
ComputeSum
)
{
for
(
int
i
=
0
;
i
<
integrator
.
getNumGlobalVariables
();
i
++
)
if
(
usesVariable
(
expression
[
step
][
0
],
integrator
.
getGlobalVariableName
(
i
)))
needsGlobals
[
step
]
=
true
;
for
(
int
i
=
0
;
i
<
(
int
)
parameterNames
.
size
();
i
++
)
if
(
usesVariable
(
expression
[
step
][
0
],
parameterNames
[
i
]))
needsGlobals
[
step
]
=
true
;
}
invalidatesForces[step] = (stepType[step] == CustomIntegrator::ConstrainPositions || affectsForce.find(variable[step]) != affectsForce.end());
if (forceGroup[step] == -2 && step > 0)
forceGroup[step] = forceGroup[step-1];
if (forceGroup[step] != -2 && savedForces.find(forceGroup[step]) == savedForces.end())
savedForces[forceGroup[step]] = new OpenCLArray(cl, cl.getForce().getSize(), cl.getForce().getElementSize(), "savedForces");
}
// Determine how each step will represent the position (as just a value, or a value plus a delta).
...
...
@@ -6174,9 +6165,6 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
for
(
int
step
=
1
;
step
<
numSteps
;
step
++
)
{
if
(
needsForces
[
step
]
||
needsEnergy
[
step
])
continue
;
if (stepType[step-1] == CustomIntegrator::ComputeGlobal && stepType[step] == CustomIntegrator::ComputeGlobal &&
!usesVariable(expression[step], "uniform") && !usesVariable(expression[step], "gaussian"))
merged[step] = true;
if
(
stepType
[
step
-
1
]
==
CustomIntegrator
::
ComputePerDof
&&
stepType
[
step
]
==
CustomIntegrator
::
ComputePerDof
)
merged
[
step
]
=
true
;
}
...
...
@@ -6196,15 +6184,15 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
}
int
numGaussian
=
0
,
numUniform
=
0
;
for
(
int
j
=
step
;
j
<
numSteps
&&
(
j
==
step
||
merged
[
j
]);
j
++
)
{
numGaussian += numAtoms*usesVariable(expression[j], "gaussian");
numUniform += numAtoms*usesVariable(expression[j], "uniform");
numGaussian
+=
numAtoms
*
usesVariable
(
expression
[
j
]
[
0
]
,
"gaussian"
);
numUniform
+=
numAtoms
*
usesVariable
(
expression
[
j
]
[
0
]
,
"uniform"
);
compute
<<
"{
\n
"
;
if
(
numGaussian
>
0
)
compute
<<
"float4 gaussian = gaussianValues[gaussianIndex+index];
\n
"
;
if
(
numUniform
>
0
)
compute
<<
"float4 uniform = uniformValues[uniformIndex+index];
\n
"
;
for
(
int
i
=
0
;
i
<
3
;
i
++
)
compute << createPerDofComputation(stepType[j] == CustomIntegrator::ComputePerDof ? variable[j] : "", expression[j], i, integrator, forceName[j], energyName[j]);
compute
<<
createPerDofComputation
(
stepType
[
j
]
==
CustomIntegrator
::
ComputePerDof
?
variable
[
j
]
:
""
,
expression
[
j
]
[
0
]
,
i
,
integrator
,
forceName
[
j
],
energyName
[
j
]);
if
(
variable
[
j
]
==
"x"
)
{
if
(
storePosAsDelta
[
j
])
{
if
(
cl
.
getSupportsDoublePrecision
())
...
...
@@ -6257,7 +6245,6 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
kernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
cl
.
getForce
().
getDeviceBuffer
());
kernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
integration
.
getStepSize
().
getDeviceBuffer
());
kernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
globalValues
->
getDeviceBuffer
());
kernel.setArg<cl::Buffer>(index++, contextParameterValues->getDeviceBuffer());
kernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
sumBuffer
->
getDeviceBuffer
());
index
+=
4
;
for
(
int
i
=
0
;
i
<
(
int
)
perDofValues
->
getBuffers
().
size
();
i
++
)
...
...
@@ -6270,41 +6257,10 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
kernels
[
step
].
push_back
(
kernel
);
index
=
0
;
kernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
sumBuffer
->
getDeviceBuffer
());
bool found = false;
for (int j = 0; j < integrator.getNumGlobalVariables() && !found; j++)
if (variable[step] == integrator.getGlobalVariableName(j)) {
kernel.setArg<cl::Buffer>(index++, globalValues->getDeviceBuffer());
kernel.setArg<cl_uint>(index++, j);
found = true;
}
for (int j = 0; j < (int) parameterNames.size() && !found; j++)
if (variable[step] == parameterNames[j]) {
kernel.setArg<cl::Buffer>(index++, contextParameterValues->getDeviceBuffer());
kernel.setArg<cl_uint>(index++, j);
found = true;
modifiesParameters = true;
}
if (!found)
throw OpenMMException("Unknown global variable: "+variable[step]);
kernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
summedValue
->
getDeviceBuffer
());
kernel
.
setArg
<
cl_int
>
(
index
++
,
3
*
numAtoms
);
}
}
else if (stepType[step] == CustomIntegrator::ComputeGlobal && !merged[step]) {
// Compute a global value.
stringstream compute;
for (int i = step; i < numSteps && (i == step || merged[i]); i++)
compute << "{\n" << createGlobalComputation(variable[i], expression[i], integrator, energyName[i]) << "}\n";
map<string, string> replacements;
replacements["COMPUTE_STEP"] = compute.str();
cl::Program program = cl.createProgram(cl.replaceStrings(OpenCLKernelSources::customIntegratorGlobal, replacements), defines);
cl::Kernel kernel = cl::Kernel(program, "computeGlobal");
kernels[step].push_back(kernel);
int index = 0;
kernel.setArg<cl::Buffer>(index++, integration.getStepSize().getDeviceBuffer());
kernel.setArg<cl::Buffer>(index++, globalValues->getDeviceBuffer());
kernel.setArg<cl::Buffer>(index++, contextParameterValues->getDeviceBuffer());
}
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
ConstrainPositions
)
{
// Apply position constraints.
...
...
@@ -6377,7 +6333,6 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
kineticEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
cl
.
getForce
().
getDeviceBuffer
());
kineticEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
integration
.
getStepSize
().
getDeviceBuffer
());
kineticEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
globalValues
->
getDeviceBuffer
());
kineticEnergyKernel.setArg<cl::Buffer>(index++, contextParameterValues->getDeviceBuffer());
kineticEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
sumBuffer
->
getDeviceBuffer
());
index
+=
2
;
kineticEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
uniformRandoms
->
getDeviceBuffer
());
...
...
@@ -6395,12 +6350,11 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
sumKineticEnergyKernel
=
cl
::
Kernel
(
program
,
useDouble
?
"computeDoubleSum"
:
"computeFloatSum"
);
index
=
0
;
sumKineticEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
sumBuffer
->
getDeviceBuffer
());
sumKineticEnergyKernel.setArg<cl::Buffer>(index++, kineticEnergy->getDeviceBuffer());
sumKineticEnergyKernel.setArg<cl_int>(index++, 0);
sumKineticEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
index
++
,
summedValue
->
getDeviceBuffer
());
sumKineticEnergyKernel
.
setArg
<
cl_int
>
(
index
++
,
3
*
numAtoms
);
}
// Make sure all values (variables, parameters, etc.)
stored on the device
are up to date.
// Make sure all values (variables, parameters, etc.) are up to date.
if
(
!
deviceValuesAreCurrent
)
{
if
(
useDouble
)
...
...
@@ -6412,38 +6366,14 @@ void OpenCLIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context
localValuesAreCurrent
=
false
;
double
stepSize
=
integrator
.
getStepSize
();
if
(
stepSize
!=
prevStepSize
)
{
if (useDouble) {
mm_double2 ss = mm_double2(0, stepSize);
integration.getStepSize().upload(&ss);
recordGlobalValue
(
stepSize
,
GlobalTarget
(
DT
,
dtVariableIndex
));
}
else {
mm_float2 ss = mm_float2(0, (float) stepSize);
integration.getStepSize().upload(&ss);
}
prevStepSize = stepSize;
}
bool paramsChanged = false;
if (useDouble) {
for
(
int
i
=
0
;
i
<
(
int
)
parameterNames
.
size
();
i
++
)
{
double
value
=
context
.
getParameter
(
parameterNames
[
i
]);
if (value != contextValuesDouble[i]) {
contextValuesDouble[i] = value;
paramsChanged = true;
}
}
if (paramsChanged)
contextParameterValues->upload(contextValuesDouble);
}
else {
for (int i = 0; i < (int) parameterNames.size(); i++) {
float value = (float) context.getParameter(parameterNames[i]);
if (value != contextValuesFloat[i]) {
contextValuesFloat[i] = value;
paramsChanged = true;
}
if
(
value
!=
globalValuesDouble
[
parameterVariableIndex
[
i
]])
{
globalValuesDouble
[
parameterVariableIndex
[
i
]]
=
value
;
deviceGlobalsAreCurrent
=
false
;
}
if (paramsChanged)
contextParameterValues->upload(contextValuesFloat);
}
}
...
...
@@ -6455,9 +6385,10 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
// Loop over computation steps in the integrator and execute them.
for (int i = 0; i < numSteps; i++) {
for
(
int
step
=
0
;
step
<
numSteps
;
)
{
int
nextStep
=
step
+
1
;
int
lastForceGroups
=
context
.
getLastForceGroups
();
if ((needsForces[
i
] || needsEnergy[
i
]) && (!forcesAreValid || lastForceGroups != forceGroup
[i
])) {
if
((
needsForces
[
step
]
||
needsEnergy
[
step
])
&&
(
!
forcesAreValid
||
lastForceGroups
!=
forceGroup
Flags
[
step
]))
{
if
(
forcesAreValid
&&
savedForces
.
find
(
lastForceGroups
)
!=
savedForces
.
end
())
{
// The forces are still valid. We just need a different force group right now. Save the old
// forces in case we need them again.
...
...
@@ -6471,79 +6402,99 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
// Recompute forces and/or energy. Figure out what is actually needed
// between now and the next time they get invalidated again.
bool computeForce = false, computeEnergy = false;
for (int j = i; ; j++) {
if (needsForces[j])
computeForce = true;
if (needsEnergy[j])
computeEnergy = true;
if (invalidatesForces[j])
break;
if (j == numSteps-1)
j = -1;
if (j == i-1)
break;
}
if (!computeEnergy && validSavedForces.find(forceGroup[i]) != validSavedForces.end()) {
bool
computeForce
=
(
needsForces
[
step
]
||
computeBothForceAndEnergy
[
step
]);
bool
computeEnergy
=
(
needsEnergy
[
step
]
||
computeBothForceAndEnergy
[
step
]);
if
(
!
computeEnergy
&&
validSavedForces
.
find
(
forceGroupFlags
[
step
])
!=
validSavedForces
.
end
())
{
// We can just restore the forces we saved earlier.
savedForces[forceGroup
[i
]]->copyTo(cl.getForce());
savedForces
[
forceGroup
Flags
[
step
]]
->
copyTo
(
cl
.
getForce
());
}
else
{
recordChangedParameters
(
context
);
energy = context.calcForcesAndEnergy(computeForce, computeEnergy, forceGroup
[i
]);
energy
=
context
.
calcForcesAndEnergy
(
computeForce
,
computeEnergy
,
forceGroup
Flags
[
step
]);
forcesAreValid
=
true
;
}
}
if (stepType[i] == CustomIntegrator::ComputePerDof && !merged[i]) {
kernels[i][0].setArg<cl_uint>(10, integration.prepareRandomNumbers(requiredGaussian[i]));
kernels[i][0].setArg<cl::Buffer>(9, integration.getRandom().getDeviceBuffer());
kernels[i][0].setArg<cl::Buffer>(11, uniformRandoms->getDeviceBuffer());
if (cl.getUseDoublePrecision())
kernels[i][0].setArg<cl_double>(12, energy);
else
kernels[i][0].setArg<cl_float>(12, (cl_float) energy);
if (requiredUniform[i] > 0)
cl.executeKernel(randomKernel, numAtoms);
cl.executeKernel(kernels[i][0], numAtoms);
if
(
needsGlobals
[
step
]
&&
!
deviceGlobalsAreCurrent
)
{
// Upload the global values to the device.
if
(
cl
.
getUseDoublePrecision
()
||
cl
.
getUseMixedPrecision
())
globalValues
->
upload
(
globalValuesDouble
);
else
{
for
(
int
j
=
0
;
j
<
(
int
)
globalValuesDouble
.
size
();
j
++
)
globalValuesFloat
[
j
]
=
(
float
)
globalValuesDouble
[
j
];
globalValues
->
upload
(
globalValuesFloat
);
}
else if (stepType[i] == CustomIntegrator::ComputeGlobal && !merged[i]) {
kernels[i][0].setArg<cl_float>(3, (cl_float) SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber());
kernels[i][0].setArg<cl_float>(4, (cl_float) SimTKOpenMMUtilities::getNormallyDistributedRandomNumber());
}
if
(
stepType
[
step
]
==
CustomIntegrator
::
ComputePerDof
&&
!
merged
[
step
])
{
kernels
[
step
][
0
].
setArg
<
cl_uint
>
(
9
,
integration
.
prepareRandomNumbers
(
requiredGaussian
[
step
]));
kernels
[
step
][
0
].
setArg
<
cl
::
Buffer
>
(
8
,
integration
.
getRandom
().
getDeviceBuffer
());
kernels
[
step
][
0
].
setArg
<
cl
::
Buffer
>
(
10
,
uniformRandoms
->
getDeviceBuffer
());
if
(
cl
.
getUseDoublePrecision
())
kernels[
i
][0].setArg<cl_double>(
5
, energy);
kernels
[
step
][
0
].
setArg
<
cl_double
>
(
11
,
energy
);
else
kernels[i][0].setArg<cl_float>(5, (cl_float) energy);
cl.executeKernel(kernels[i][0], 1, 1);
}
else if (stepType[i] == CustomIntegrator::ComputeSum) {
kernels[i][0].setArg<cl_uint>(10, integration.prepareRandomNumbers(requiredGaussian[i]));
kernels[i][0].setArg<cl::Buffer>(9, integration.getRandom().getDeviceBuffer());
kernels[i][0].setArg<cl::Buffer>(11, uniformRandoms->getDeviceBuffer());
kernels
[
step
][
0
].
setArg
<
cl_float
>
(
11
,
(
cl_float
)
energy
);
if
(
requiredUniform
[
step
]
>
0
)
cl
.
executeKernel
(
randomKernel
,
numAtoms
);
cl
.
executeKernel
(
kernels
[
step
][
0
],
numAtoms
);
}
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
ComputeGlobal
)
{
expressionSet
.
setVariable
(
uniformVariableIndex
,
SimTKOpenMMUtilities
::
getUniformlyDistributedRandomNumber
());
expressionSet
.
setVariable
(
gaussianVariableIndex
,
SimTKOpenMMUtilities
::
getNormallyDistributedRandomNumber
());
expressionSet
.
setVariable
(
stepEnergyVariableIndex
[
step
],
energy
);
recordGlobalValue
(
globalExpressions
[
step
][
0
].
evaluate
(),
stepTarget
[
step
]);
}
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
ComputeSum
)
{
kernels
[
step
][
0
].
setArg
<
cl_uint
>
(
9
,
integration
.
prepareRandomNumbers
(
requiredGaussian
[
step
]));
kernels
[
step
][
0
].
setArg
<
cl
::
Buffer
>
(
8
,
integration
.
getRandom
().
getDeviceBuffer
());
kernels
[
step
][
0
].
setArg
<
cl
::
Buffer
>
(
10
,
uniformRandoms
->
getDeviceBuffer
());
if
(
cl
.
getUseDoublePrecision
())
kernels[
i
][0].setArg<cl_double>(1
2
, energy);
kernels
[
step
][
0
].
setArg
<
cl_double
>
(
1
1
,
energy
);
else
kernels[
i
][0].setArg<cl_float>(1
2
, (cl_float) energy);
if (requiredUniform[
i
] > 0)
kernels
[
step
][
0
].
setArg
<
cl_float
>
(
1
1
,
(
cl_float
)
energy
);
if
(
requiredUniform
[
step
]
>
0
)
cl
.
executeKernel
(
randomKernel
,
numAtoms
);
cl
.
clearBuffer
(
*
sumBuffer
);
cl.executeKernel(kernels[i][0], numAtoms);
cl.executeKernel(kernels[i][1], OpenCLContext::ThreadBlockSize, OpenCLContext::ThreadBlockSize);
cl
.
executeKernel
(
kernels
[
step
][
0
],
numAtoms
);
cl
.
executeKernel
(
kernels
[
step
][
1
],
OpenCLContext
::
ThreadBlockSize
,
OpenCLContext
::
ThreadBlockSize
);
if
(
cl
.
getUseDoublePrecision
()
||
cl
.
getUseMixedPrecision
())
{
double
value
;
summedValue
->
download
(
&
value
);
globalValuesDouble
[
stepTarget
[
step
].
variableIndex
]
=
value
;
}
else
{
float
value
;
summedValue
->
download
(
&
value
);
globalValuesDouble
[
stepTarget
[
step
].
variableIndex
]
=
value
;
}
else if (stepType[i] == CustomIntegrator::UpdateContextState) {
}
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
UpdateContextState
)
{
recordChangedParameters
(
context
);
context
.
updateContextState
();
}
else if (stepType[
i
] == CustomIntegrator::ConstrainPositions) {
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
ConstrainPositions
)
{
cl
.
getIntegrationUtilities
().
applyConstraints
(
integrator
.
getConstraintTolerance
());
cl.executeKernel(kernels[
i
][0], numAtoms);
cl
.
executeKernel
(
kernels
[
step
][
0
],
numAtoms
);
cl
.
getIntegrationUtilities
().
computeVirtualSites
();
}
else if (stepType[
i
] == CustomIntegrator::ConstrainVelocities) {
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
ConstrainVelocities
)
{
cl
.
getIntegrationUtilities
().
applyVelocityConstraints
(
integrator
.
getConstraintTolerance
());
}
if (invalidatesForces[i])
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
BeginIfBlock
)
{
if
(
!
evaluateCondition
(
step
))
nextStep
=
blockEnd
[
step
]
+
1
;
}
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
BeginWhileBlock
)
{
if
(
!
evaluateCondition
(
step
))
nextStep
=
blockEnd
[
step
]
+
1
;
}
else
if
(
stepType
[
step
]
==
CustomIntegrator
::
EndBlock
)
{
if
(
blockEnd
[
step
]
!=
-
1
)
nextStep
=
blockEnd
[
step
];
// Return to the start of a while block.
}
if
(
invalidatesForces
[
step
])
forcesAreValid
=
false
;
step
=
nextStep
;
}
recordChangedParameters
(
context
);
...
...
@@ -6564,6 +6515,29 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
#endif
}
bool
OpenCLIntegrateCustomStepKernel
::
evaluateCondition
(
int
step
)
{
expressionSet
.
setVariable
(
uniformVariableIndex
,
SimTKOpenMMUtilities
::
getUniformlyDistributedRandomNumber
());
expressionSet
.
setVariable
(
gaussianVariableIndex
,
SimTKOpenMMUtilities
::
getNormallyDistributedRandomNumber
());
expressionSet
.
setVariable
(
stepEnergyVariableIndex
[
step
],
energy
);
double
lhs
=
globalExpressions
[
step
][
0
].
evaluate
();
double
rhs
=
globalExpressions
[
step
][
1
].
evaluate
();
switch
(
comparisons
[
step
])
{
case
CustomIntegratorUtilities
::
EQUAL
:
return
(
lhs
==
rhs
);
case
CustomIntegratorUtilities
::
LESS_THAN
:
return
(
lhs
<
rhs
);
case
CustomIntegratorUtilities
::
GREATER_THAN
:
return
(
lhs
>
rhs
);
case
CustomIntegratorUtilities
::
NOT_EQUAL
:
return
(
lhs
!=
rhs
);
case
CustomIntegratorUtilities
::
LESS_THAN_OR_EQUAL
:
return
(
lhs
<=
rhs
);
case
CustomIntegratorUtilities
::
GREATER_THAN_OR_EQUAL
:
return
(
lhs
>=
rhs
);
}
throw
OpenMMException
(
"Invalid comparison operator"
);
}
double
OpenCLIntegrateCustomStepKernel
::
computeKineticEnergy
(
ContextImpl
&
context
,
CustomIntegrator
&
integrator
,
bool
&
forcesAreValid
)
{
prepareForComputation
(
context
,
integrator
,
forcesAreValid
);
if
(
keNeedsForce
&&
!
forcesAreValid
)
{
...
...
@@ -6577,69 +6551,81 @@ double OpenCLIntegrateCustomStepKernel::computeKineticEnergy(ContextImpl& contex
forcesAreValid
=
true
;
}
cl
.
clearBuffer
(
*
sumBuffer
);
kineticEnergyKernel.setArg<cl::Buffer>(
9
, cl.getIntegrationUtilities().getRandom().getDeviceBuffer());
kineticEnergyKernel.setArg<cl_uint>(
10
, 0);
kineticEnergyKernel
.
setArg
<
cl
::
Buffer
>
(
8
,
cl
.
getIntegrationUtilities
().
getRandom
().
getDeviceBuffer
());
kineticEnergyKernel
.
setArg
<
cl_uint
>
(
9
,
0
);
cl
.
executeKernel
(
kineticEnergyKernel
,
cl
.
getNumAtoms
());
cl
.
executeKernel
(
sumKineticEnergyKernel
,
OpenCLContext
::
ThreadBlockSize
,
OpenCLContext
::
ThreadBlockSize
);
if
(
cl
.
getUseDoublePrecision
()
||
cl
.
getUseMixedPrecision
())
{
double
ke
;
kineticEnergy
->download(&ke);
summedValue
->
download
(
&
ke
);
return
ke
;
}
else
{
float
ke
;
kineticEnergy
->download(&ke);
summedValue
->
download
(
&
ke
);
return
ke
;
}
}
void
OpenCLIntegrateCustomStepKernel
::
recordGlobalValue
(
double
value
,
GlobalTarget
target
)
{
switch
(
target
.
type
)
{
case
DT
:
globalValuesDouble
[
dtVariableIndex
]
=
value
;
deviceGlobalsAreCurrent
=
false
;
if
(
cl
.
getUseDoublePrecision
()
||
cl
.
getUseMixedPrecision
())
{
double
size
[]
=
{
0
,
value
};
cl
.
getIntegrationUtilities
().
getStepSize
().
upload
(
size
);
}
else
{
float
size
[]
=
{
0
,
(
float
)
value
};
cl
.
getIntegrationUtilities
().
getStepSize
().
upload
(
size
);
}
prevStepSize
=
value
;
break
;
case
VARIABLE
:
case
PARAMETER
:
expressionSet
.
setVariable
(
target
.
variableIndex
,
value
);
globalValuesDouble
[
target
.
variableIndex
]
=
value
;
deviceGlobalsAreCurrent
=
false
;
break
;
}
}
void
OpenCLIntegrateCustomStepKernel
::
recordChangedParameters
(
ContextImpl
&
context
)
{
if
(
!
modifiesParameters
)
return
;
if (cl.getUseDoublePrecision() || cl.getUseMixedPrecision()) {
contextParameterValues->download(contextValuesDouble);
for
(
int
i
=
0
;
i
<
(
int
)
parameterNames
.
size
();
i
++
)
{
double
value
=
context
.
getParameter
(
parameterNames
[
i
]);
if (value != contextValuesDouble[i])
context.setParameter(parameterNames[i], contextValuesDouble[i]);
}
}
else {
contextParameterValues->download(contextValuesFloat);
for (int i = 0; i < (int) parameterNames.size(); i++) {
float value = (float) context.getParameter(parameterNames[i]);
if (value != contextValuesFloat[i])
context.setParameter(parameterNames[i], contextValuesFloat[i]);
}
if
(
value
!=
globalValuesDouble
[
parameterVariableIndex
[
i
]])
context
.
setParameter
(
parameterNames
[
i
],
globalValuesDouble
[
parameterVariableIndex
[
i
]]);
}
}
void
OpenCLIntegrateCustomStepKernel
::
getGlobalVariables
(
ContextImpl
&
context
,
vector
<
double
>&
values
)
const
{
if (numGlobalVariables == 0) {
values.resize(0);
return;
if
(
globalValues
==
NULL
)
{
// The data structures haven't been created yet, so just return the list of values that was given earlier.
values
=
initialGlobalVariables
;
}
if (cl.getUseDoublePrecision() || cl.getUseMixedPrecision())
globalValues->download(values);
else {
vector<cl_float> buffer;
globalValues->download(buffer);
values
.
resize
(
numGlobalVariables
);
for
(
int
i
=
0
;
i
<
numGlobalVariables
;
i
++
)
values[i] = buffer[i];
}
values
[
i
]
=
globalValuesDouble
[
globalVariableIndex
[
i
]];
}
void
OpenCLIntegrateCustomStepKernel
::
setGlobalVariables
(
ContextImpl
&
context
,
const
vector
<
double
>&
values
)
{
if
(
numGlobalVariables
==
0
)
return
;
if (cl.getUseDoublePrecision() || cl.getUseMixedPrecision())
globalValues->upload(values);
else {
vector<cl_float> buffer(numGlobalVariables);
for (int i = 0; i < numGlobalVariables; i++)
buffer[i] = (cl_float) values[i];
globalValues->upload(buffer);
if
(
globalValues
==
NULL
)
{
// The data structures haven't been created yet, so just store the list of values.
initialGlobalVariables
=
values
;
return
;
}
for
(
int
i
=
0
;
i
<
numGlobalVariables
;
i
++
)
{
globalValuesDouble
[
globalVariableIndex
[
i
]]
=
values
[
i
];
expressionSet
.
setVariable
(
globalVariableIndex
[
i
],
values
[
i
]);
}
deviceGlobalsAreCurrent
=
false
;
}
void
OpenCLIntegrateCustomStepKernel
::
getPerDofVariable
(
ContextImpl
&
context
,
int
variable
,
vector
<
Vec3
>&
values
)
const
{
...
...
platforms/opencl/src/kernels/customIntegrator.cl
View file @
9ddded35
__kernel
void
computeFloatSum
(
__global
const
float*
restrict
sumBuffer,
__global
float*
result,
unsigned
int
outputIndex,
int
bufferSize
)
{
__kernel
void
computeFloatSum
(
__global
const
float*
restrict
sumBuffer,
__global
float*
result,
int
bufferSize
)
{
__local
float
tempBuffer[WORK_GROUP_SIZE]
;
const
unsigned
int
thread
=
get_local_id
(
0
)
;
float
sum
=
0
;
...
...
@@ -11,11 +11,11 @@ __kernel void computeFloatSum(__global const float* restrict sumBuffer, __global
tempBuffer[thread]
+=
tempBuffer[thread+i]
;
}
if
(
thread
==
0
)
result
[outputIndex]
=
tempBuffer[0]
;
*
result
=
tempBuffer[0]
;
}
#
ifdef
SUPPORTS_DOUBLE_PRECISION
__kernel
void
computeDoubleSum
(
__global
const
double*
restrict
sumBuffer,
__global
double*
result,
unsigned
int
outputIndex,
int
bufferSize
)
{
__kernel
void
computeDoubleSum
(
__global
const
double*
restrict
sumBuffer,
__global
double*
result,
int
bufferSize
)
{
__local
double
tempBuffer[WORK_GROUP_SIZE]
;
const
unsigned
int
thread
=
get_local_id
(
0
)
;
double
sum
=
0
;
...
...
@@ -28,7 +28,7 @@ __kernel void computeDoubleSum(__global const double* restrict sumBuffer, __glob
tempBuffer[thread]
+=
tempBuffer[thread+i]
;
}
if
(
thread
==
0
)
result
[outputIndex]
=
tempBuffer[0]
;
*
result
=
tempBuffer[0]
;
}
#
endif
...
...
platforms/opencl/src/kernels/customIntegratorGlobal.cl
deleted
100644 → 0
View file @
506908ce
__kernel
void
computeGlobal
(
__global
mixed2*
restrict
dt,
__global
mixed*
restrict
globals,
__global
mixed*
restrict
params,
float
uniform,
float
gaussian,
const
real
energy
)
{
COMPUTE_STEP
}
platforms/opencl/src/kernels/customIntegratorPerDof.cl
View file @
9ddded35
...
...
@@ -25,8 +25,7 @@ void storePos(__global real4* restrict posq, __global real4* restrict posqCorrec
__kernel
void
computePerDof
(
__global
real4*
restrict
posq,
__global
real4*
restrict
posqCorrection,
__global
mixed4*
restrict
posDelta,
__global
mixed4*
restrict
velm,
__global
const
real4*
restrict
force,
__global
const
mixed2*
restrict
dt,
__global
const
mixed*
restrict
globals,
__global
const
mixed*
restrict
params,
__global
mixed*
restrict
sum,
__global
const
float4*
restrict
gaussianValues,
unsigned
int
gaussianBaseIndex,
__global
const
float4*
restrict
uniformValues,
const
real
energy
__global
mixed*
restrict
sum,
__global
const
float4*
restrict
gaussianValues,
unsigned
int
gaussianBaseIndex,
__global
const
float4*
restrict
uniformValues,
const
real
energy
PARAMETER_ARGUMENTS
)
{
mixed
stepSize
=
dt[0].y
;
int
index
=
get_global_id
(
0
)
;
...
...
platforms/opencl/tests/TestOpenCLCustomIntegrator.cpp
View file @
9ddded35
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -756,6 +756,66 @@ void testMergedRandoms() {
}
}
void
testIfBlock
()
{
System
system
;
system
.
addParticle
(
2.0
);
system
.
addParticle
(
2.0
);
const
double
dt
=
0.01
;
CustomIntegrator
integrator
(
dt
);
integrator
.
addGlobalVariable
(
"a"
,
0
);
integrator
.
addGlobalVariable
(
"b"
,
0
);
integrator
.
addComputeGlobal
(
"b"
,
"1"
);
integrator
.
beginIfBlock
(
"a < 3.5"
);
integrator
.
addComputeGlobal
(
"b"
,
"a+1"
);
integrator
.
endBlock
();
Context
context
(
system
,
integrator
,
platform
);
// Set "a" to 1.7 and verify that "b" gets set to a+1.
integrator
.
setGlobalVariable
(
0
,
1.7
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
2.7
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
// Now set it to a value that should cause the block to be skipped.
integrator
.
setGlobalVariable
(
0
,
4.1
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
1.0
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
}
void
testWhileBlock
()
{
System
system
;
system
.
addParticle
(
2.0
);
system
.
addParticle
(
2.0
);
const
double
dt
=
0.01
;
CustomIntegrator
integrator
(
dt
);
integrator
.
addGlobalVariable
(
"a"
,
0
);
integrator
.
addGlobalVariable
(
"b"
,
0
);
integrator
.
addComputeGlobal
(
"b"
,
"1"
);
integrator
.
beginWhileBlock
(
"b <= a"
);
integrator
.
addComputeGlobal
(
"b"
,
"b+1"
);
integrator
.
endBlock
();
Context
context
(
system
,
integrator
,
platform
);
// Try a case where the loop should be skipped.
integrator
.
setGlobalVariable
(
0
,
-
3.3
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
1.0
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
// In this case it should be executed exactly once.
integrator
.
setGlobalVariable
(
0
,
1.2
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
2.0
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
// In this case, it should be executed several times.
integrator
.
setGlobalVariable
(
0
,
5.3
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
6.0
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
if
(
argc
>
1
)
...
...
@@ -773,6 +833,8 @@ int main(int argc, char* argv[]) {
testForceGroups
();
testRespa
();
testMergedRandoms
();
testIfBlock
();
testWhileBlock
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
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