OpenCLContext.h 10.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef OPENMM_OPENCLCONTEXT_H_
#define OPENMM_OPENCLCONTEXT_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.           *
 * Authors: Peter Eastman                                                     *
 * 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/>.      *
 * -------------------------------------------------------------------------- */

#define __CL_ENABLE_EXCEPTIONS
31
32
#include <map>
#include <string>
33
#include <cl.hpp>
34
35
36
37
38

namespace OpenMM {

template <class T>
class OpenCLArray;
39
class OpenCLForceInfo;
40
class OpenCLIntegrationUtilities;
41
class OpenCLNonbondedUtilities;
42
class System;
43

44
/**
45
46
47
 * We can't use predefined vector types like cl_float4, since different OpenCL implementations currently define
 * them in incompatible ways.  Hopefully that will be fixed in the future.  In the mean time, we define our own
 * types to represent them on the host.
48
49
 */

50
51
52
typedef struct {
    cl_float x, y;
} mm_float2;
53
54
55
typedef struct {
    cl_float x, y, z, w;
} mm_float4;
56
57
58
typedef struct {
    cl_float s0, s1, s2, s3, s4, s5, s6, s7;
} mm_float8;
59
60
61
62
63
64
typedef struct {
    cl_int x, y;
} mm_int2;
typedef struct {
    cl_int x, y, z, w;
} mm_int4;
65
66
67
typedef struct {
    cl_int s0, s1, s2, s3, s4, s5, s6, s7;
} mm_int8;
68

69
70
71
72
73
74
/**
 * This class contains the information associated with a Context by the OpenCL Platform.
 */

class OpenCLContext {
public:
75
76
    static const int ThreadBlockSize = 64;
    static const int TileSize = 32;
77
    OpenCLContext(int numParticles, int deviceIndex);
78
    ~OpenCLContext();
79
80
81
82
83
84
85
86
87
    /**
     * This is called to initialize internal data structures after all Forces in the system
     * have been initialized.
     */
    void initialize(const System& system);
    /**
     * Add an OpenCLForce to this context.
     */
    void addForce(OpenCLForceInfo* force);
88
89
90
91
    /**
     * Get the cl::Context associated with this object.
     */
    cl::Context& getContext() {
92
        return context;
93
    }
94
95
96
97
98
99
    /**
     * Get the cl::Device associated with this object.
     */
    cl::Device& getDevice() {
        return device;
    }
Peter Eastman's avatar
Peter Eastman committed
100
101
102
103
104
105
    /**
     * Get the index of the cl::Device associated with this object.
     */
    int getDeviceIndex() {
        return deviceIndex;
    }
106
107
108
109
    /**
     * Get the cl::CommandQueue associated with this object.
     */
    cl::CommandQueue& getQueue() {
110
        return queue;
111
112
113
114
    }
    /**
     * Get the array which contains the position and charge of each atom.
     */
115
    OpenCLArray<mm_float4>& getPosq() {
116
117
118
        return *posq;
    }
    /**
119
     * Get the array which contains the velocity and inverse mass of each atom.
120
     */
121
    OpenCLArray<mm_float4>& getVelm() {
122
123
124
125
126
        return *velm;
    }
    /**
     * Get the array which contains the force on each atom.
     */
127
    OpenCLArray<mm_float4>& getForce() {
128
129
        return *force;
    }
130
131
132
    /**
     * Get the array which contains the buffers in which forces are computed.
     */
133
    OpenCLArray<mm_float4>& getForceBuffers() {
134
135
        return *forceBuffers;
    }
136
137
138
139
140
141
    /**
     * Get the array which contains the buffer in which energy is computed.
     */
    OpenCLArray<cl_float>& getEnergyBuffer() {
        return *energyBuffer;
    }
142
143
144
145
146
147
    /**
     * Get the array which contains the index of each atom.
     */
    OpenCLArray<cl_int>& getAtomIndex() {
        return *atomIndex;
    }
148
149
150
151
152
153
    /**
     * Get the number of cells by which the positions are offset.
     */
    std::vector<mm_int4>& getPosCellOffsets() {
        return posCellOffsets;
    }
154
155
156
157
    /**
     * Load OpenCL source code from a file in the kernels directory.
     */
    std::string loadSourceFromFile(const std::string& filename) const;
158
159
160
161
162
163
164
    /**
     * Load OpenCL source code from a file in the kernels directory.
     *
     * @param filename     the file to load
     * @param replacements a set of strings that should be replaced with new strings wherever they appear in the
     */
    std::string loadSourceFromFile(const std::string& filename, const std::map<std::string, std::string>& replacements) const;
165
166
167
168
    /**
     * Create an OpenCL Program from source code.
     */
    cl::Program createProgram(const std::string source);
169
170
171
172
173
174
    /**
     * Create an OpenCL Program from source code.
     *
     * @param defines    a set of preprocessor definitions (name, value) to define when compiling the program
     */
    cl::Program createProgram(const std::string source, const std::map<std::string, std::string>& defines);
175
176
177
    /**
     * Execute a kernel.
     *
178
179
     * @param kernel       the kernel to execute
     * @param workUnits    the maximum number of work units that should be used
180
     * @param blockSize    the size of each thread block to use
181
     */
182
    void executeKernel(cl::Kernel& kernel, int workUnits, int blockSize = -1);
183
184
185
186
187
188
189
    /**
     * Set all elements of an array to 0.
     */
    void clearBuffer(OpenCLArray<float>& array);
    /**
     * Set all elements of an array to 0.
     */
190
    void clearBuffer(OpenCLArray<mm_float4>& array);
191
192
193
194
195
196
197
198
    /**
     * Given a collection of buffers packed into an array, sum them and store
     * the sum in the first buffer.
     *
     * @param array       the array containing the buffers to reduce
     * @param numBuffers  the number of buffers packed into the array
     */
    void reduceBuffer(OpenCLArray<mm_float4>& array, int numBuffers);
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    /**
     * Get the current simulation time.
     */
    double getTime() {
        return time;
    }
    /**
     * Set the current simulation time.
     */
    void setTime(double t) {
        time = t;
    }
    /**
     * Get the number of integration steps that have been taken.
     */
    int getStepCount() {
        return stepCount;
    }
    /**
     * Set the number of integration steps that have been taken.
     */
    void setStepCount(int steps) {
221
222
223
224
225
226
227
228
229
230
231
232
233
        stepCount = steps;
    }
    /**
     * Get the number of times forces or energy has been computed.
     */
    int getComputeForceCount() {
        return computeForceCount;
    }
    /**
     * Set the number of times forces or energy has been computed.
     */
    void setComputeForceCount(int count) {
        computeForceCount = count;
234
    }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    /**
     * Get the number of atoms.
     */
    int getNumAtoms() const {
        return numAtoms;
    }
    /**
     * Get the number of atoms, rounded up to a multiple of TileSize.  This is the actual size of
     * most arrays with one element per atom.
     */
    int getPaddedNumAtoms() const {
        return paddedNumAtoms;
    }
    /**
     * Get the number of blocks of TileSize atoms.
     */
    int getNumAtomBlocks() const {
        return numAtomBlocks;
    }
    /**
     * Get the standard number of thread blocks to use when executing kernels.
     */
    int getNumThreadBlocks() const {
        return numThreadBlocks;
    }
    /**
     * Get the number of force buffers.
     */
    int getNumForceBuffers() const {
        return numForceBuffers;
    }
266
267
268
269
270
271
    /**
     * Get the SIMD width of the device being used.
     */
    int getSIMDWidth() const {
        return simdWidth;
    }
272
273
274
    /**
     * Get the OpenCLIntegrationUtilities for this context.
     */
275
    OpenCLIntegrationUtilities& getIntegrationUtilities() {
276
277
        return *integration;
    }
278
279
280
    /**
     * Get the OpenCLNonbondedUtilities for this context.
     */
281
    OpenCLNonbondedUtilities& getNonbondedUtilities() {
282
283
        return *nonbonded;
    }
284
285
286
287
288
    /**
     * Reorder the internal arrays of atoms to try to keep spatially contiguous atoms close
     * together in the arrays.
     */
    void reorderAtoms();
289
private:
290
291
292
293
    struct Molecule;
    struct MoleculeGroup;
    void findMoleculeGroups(const System& system);
    static void tagAtomsInMolecule(int atom, int molecule, std::vector<int>& atomMolecule, std::vector<std::vector<int> >& atomBonds);
294
    double time;
Peter Eastman's avatar
Peter Eastman committed
295
    int deviceIndex;
296
    int stepCount;
297
    int computeForceCount;
298
299
300
301
302
    int numAtoms;
    int paddedNumAtoms;
    int numAtomBlocks;
    int numThreadBlocks;
    int numForceBuffers;
303
    int simdWidth;
304
    std::string compilationOptions;
305
306
307
308
309
    cl::Context context;
    cl::Device device;
    cl::CommandQueue queue;
    cl::Program utilities;
    cl::Kernel clearBufferKernel;
310
311
    cl::Kernel reduceFloat4Kernel;
    std::vector<OpenCLForceInfo*> forces;
312
313
    std::vector<MoleculeGroup> moleculeGroups;
    std::vector<mm_int4> posCellOffsets;
314
315
316
317
    OpenCLArray<mm_float4>* posq;
    OpenCLArray<mm_float4>* velm;
    OpenCLArray<mm_float4>* force;
    OpenCLArray<mm_float4>* forceBuffers;
318
    OpenCLArray<cl_float>* energyBuffer;
319
    OpenCLArray<cl_int>* atomIndex;
320
    OpenCLIntegrationUtilities* integration;
321
    OpenCLNonbondedUtilities* nonbonded;
322
323
};

324
325
326
327
328
struct OpenCLContext::MoleculeGroup {
    std::vector<int> atoms;
    std::vector<int> instances;
};

329
330
331
} // namespace OpenMM

#endif /*OPENMM_OPENCLCONTEXT_H_*/