Commit d147fc2c authored by Peter Eastman's avatar Peter Eastman
Browse files

Created API for platform-specific properties. CudaPlatform has a property for setting the device.

parent b2038773
...@@ -34,14 +34,16 @@ ...@@ -34,14 +34,16 @@
#include "Stream.h" #include "Stream.h"
#include <map> #include <map>
#include <string>
#include <vector> #include <vector>
#include "openmm/internal/windowsExport.h" #include "openmm/internal/windowsExport.h"
namespace OpenMM { namespace OpenMM {
class Context;
class ContextImpl;
class Kernel; class Kernel;
class KernelFactory; class KernelFactory;
class ContextImpl;
class StreamFactory; class StreamFactory;
/** /**
...@@ -80,6 +82,42 @@ public: ...@@ -80,6 +82,42 @@ public:
* is permitted to implement double precision streams internally as single precision. * is permitted to implement double precision streams internally as single precision.
*/ */
virtual bool supportsDoublePrecision() const = 0; virtual bool supportsDoublePrecision() const = 0;
/**
* Get the names of all Platform-specific properties this Platform supports.
*/
const std::vector<std::string>& getPropertyNames();
/**
* Get the value of a Platform-specific property for a Context.
*
* @param context the Context for which to get the property
* @param property the name of the property to get
* @return the value of the property
*/
virtual const std::string& getPropertyValue(const Context& context, const std::string& property) const;
/**
* Set the value of a Platform-specific property for a Context.
*
* @param context the Context for which to set the property
* @param property the name of the property to set
* @param value the value to set for the property
*/
virtual void setPropertyValue(Context& context, const std::string& property, const std::string& value) const;
/**
* Get the default value of a Platform-specific property. This is the value that will be used for
* newly created Contexts.
*
* @param property the name of the property to get
* @return the default value of the property
*/
const std::string& getPropertyDefaultValue(const std::string& property) const;
/**
* Set the default value of a Platform-specific property. This is the value that will be used for
* newly created Contexts.
*
* @param property the name of the property to set
* @param value the value to set for the property
*/
void setPropertyDefaultValue(const std::string& property, const std::string& value);
/** /**
* Get the default StreamFactory for this Platform. It will be used to create Streams whenever a * Get the default StreamFactory for this Platform. It will be used to create Streams whenever a
* different StreamFactory has not been registered for the requested stream name. * different StreamFactory has not been registered for the requested stream name.
...@@ -199,6 +237,16 @@ public: ...@@ -199,6 +237,16 @@ public:
* @return the path to the default plugin directory * @return the path to the default plugin directory
*/ */
static const std::string& getDefaultPluginsDirectory(); static const std::string& getDefaultPluginsDirectory();
protected:
/**
* Get the ContextImpl for a Context.
*/
ContextImpl& getContextImpl(Context& context) const;
/**
* Get the ContextImpl for a Context.
*/
const ContextImpl& getContextImpl(const Context& context) const;
std::vector<std::string> platformProperties;
private: private:
// Retarded visual studio compiler complains about being unable to // Retarded visual studio compiler complains about being unable to
...@@ -211,6 +259,7 @@ private: ...@@ -211,6 +259,7 @@ private:
std::map<std::string, KernelFactory*> kernelFactories; std::map<std::string, KernelFactory*> kernelFactories;
std::map<std::string, StreamFactory*> streamFactories; std::map<std::string, StreamFactory*> streamFactories;
std::map<std::string, std::string> defaultProperties;
static std::vector<Platform*>& getPlatforms(); static std::vector<Platform*>& getPlatforms();
#if defined(_MSC_VER) #if defined(_MSC_VER)
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "openmm/Platform.h" #include "openmm/Platform.h"
#include "openmm/Context.h"
#include "openmm/OpenMMException.h" #include "openmm/OpenMMException.h"
#include "openmm/Kernel.h" #include "openmm/Kernel.h"
#include "openmm/Stream.h" #include "openmm/Stream.h"
...@@ -74,6 +75,29 @@ Platform::~Platform() { ...@@ -74,6 +75,29 @@ Platform::~Platform() {
delete *iter; delete *iter;
} }
const vector<string>& Platform::getPropertyNames() {
return platformProperties;
}
const string& Platform::getPropertyValue(const Context& context, const string& property) const {
throw OpenMMException("getPropertyValue: Illegal property name");
}
void Platform::setPropertyValue(Context& context, const string& property, const string& value) const {
throw OpenMMException("setPropertyValue: Illegal property name");
}
const string& Platform::getPropertyDefaultValue(const string& property) const {
map<string, string>::const_iterator value = defaultProperties.find(property);
if (value == defaultProperties.end())
throw OpenMMException("getPropertyDefaultValue: Illegal property name");
return value->second;
}
void Platform::setPropertyDefaultValue(const string& property, const string& value) {
defaultProperties[property] = value;
}
void Platform::contextCreated(ContextImpl& context) const { void Platform::contextCreated(ContextImpl& context) const {
} }
...@@ -217,3 +241,12 @@ const string& Platform::getDefaultPluginsDirectory() { ...@@ -217,3 +241,12 @@ const string& Platform::getDefaultPluginsDirectory() {
#endif #endif
return directory; return directory;
} }
ContextImpl& Platform::getContextImpl(Context& context) const {
return *context.impl;
}
const ContextImpl& Platform::getContextImpl(const Context& context) const {
return *context.impl;
}
...@@ -153,6 +153,7 @@ public: ...@@ -153,6 +153,7 @@ public:
*/ */
void reinitialize(); void reinitialize();
private: private:
friend class Platform;
ContextImpl* impl; ContextImpl* impl;
}; };
......
...@@ -144,6 +144,10 @@ public: ...@@ -144,6 +144,10 @@ public:
* Get the platform-specific data stored in this context. * Get the platform-specific data stored in this context.
*/ */
void* getPlatformData(); void* getPlatformData();
/**
* Get the platform-specific data stored in this context.
*/
const void* getPlatformData() const;
/** /**
* Set the platform-specific data stored in this context. * Set the platform-specific data stored in this context.
*/ */
......
...@@ -135,6 +135,10 @@ void* ContextImpl::getPlatformData() { ...@@ -135,6 +135,10 @@ void* ContextImpl::getPlatformData() {
return platformData; return platformData;
} }
const void* ContextImpl::getPlatformData() const {
return platformData;
}
void ContextImpl::setPlatformData(void* data) { void ContextImpl::setPlatformData(void* data) {
platformData = data; platformData = data;
} }
...@@ -210,7 +210,7 @@ class OPENMM_EXPORT BrookPlatform : public Platform { ...@@ -210,7 +210,7 @@ class OPENMM_EXPORT BrookPlatform : public Platform {
#define bool bool #define bool bool
bool supportsDoublePrecision( void ) const; bool supportsDoublePrecision( void ) const;
/** /**
* Return default Brook stream factory * Return default Brook stream factory
* *
* @return Brook stream factory * @return Brook stream factory
......
...@@ -454,7 +454,7 @@ bool BrookPlatform::supportsDoublePrecision( void ) const { ...@@ -454,7 +454,7 @@ bool BrookPlatform::supportsDoublePrecision( void ) const {
return (sizeof(RealOpenMM) >= sizeof(double)); return (sizeof(RealOpenMM) >= sizeof(double));
} }
/** /**
* Return Stream factory * Return Stream factory
* *
*/ */
......
...@@ -52,18 +52,25 @@ public: ...@@ -52,18 +52,25 @@ public:
return 100; return 100;
} }
bool supportsDoublePrecision() const; bool supportsDoublePrecision() const;
const std::string& getPropertyValue(const Context& context, const std::string& property) const;
void setPropertyValue(Context& context, const std::string& property, const std::string& value) const;
const StreamFactory& getDefaultStreamFactory() const; const StreamFactory& getDefaultStreamFactory() const;
void contextCreated(ContextImpl& context) const; void contextCreated(ContextImpl& context) const;
void contextDestroyed(ContextImpl& context) const; void contextDestroyed(ContextImpl& context) const;
/**
* This is the name of the parameter for selecting which CUDA device to use.
*/
static const std::string& CudaDevice() {
static const std::string key = "CudaDevice";
return key;
}
private: private:
CudaStreamFactory defaultStreamFactory; CudaStreamFactory defaultStreamFactory;
}; };
class CudaPlatform::PlatformData { class CudaPlatform::PlatformData {
public: public:
PlatformData(_gpuContext* gpu) : gpu(gpu), removeCM(false), nonbondedMethod(0), hasBonds(false), hasAngles(false), PlatformData(_gpuContext* gpu);
hasPeriodicTorsions(false), hasRB(false), hasNonbonded(false), primaryKernel(NULL), stepCount(0), computeForceCount(0), time(0.0) {
}
_gpuContext* gpu; _gpuContext* gpu;
KernelImpl* primaryKernel; KernelImpl* primaryKernel;
bool removeCM; bool removeCM;
...@@ -72,6 +79,7 @@ public: ...@@ -72,6 +79,7 @@ public:
int cmMotionFrequency; int cmMotionFrequency;
int stepCount, computeForceCount; int stepCount, computeForceCount;
double time; double time;
std::map<std::string, std::string> propertyValues;
}; };
} // namespace OpenMM } // namespace OpenMM
......
...@@ -30,9 +30,14 @@ ...@@ -30,9 +30,14 @@
#include "openmm/PluginInitializer.h" #include "openmm/PluginInitializer.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
#include "kernels/gputypes.h" #include "kernels/gputypes.h"
#include "openmm/Context.h"
#include "openmm/System.h" #include "openmm/System.h"
#include <sstream>
using namespace OpenMM; using namespace OpenMM;
using std::map;
using std::string;
using std::stringstream;
extern "C" void initOpenMMPlugin() { extern "C" void initOpenMMPlugin() {
if (gpuIsAvailable()) if (gpuIsAvailable())
...@@ -56,19 +61,37 @@ CudaPlatform::CudaPlatform() { ...@@ -56,19 +61,37 @@ CudaPlatform::CudaPlatform() {
registerKernelFactory(ApplyAndersenThermostatKernel::Name(), factory); registerKernelFactory(ApplyAndersenThermostatKernel::Name(), factory);
registerKernelFactory(CalcKineticEnergyKernel::Name(), factory); registerKernelFactory(CalcKineticEnergyKernel::Name(), factory);
registerKernelFactory(RemoveCMMotionKernel::Name(), factory); registerKernelFactory(RemoveCMMotionKernel::Name(), factory);
platformProperties.push_back(CudaDevice());
setPropertyDefaultValue(CudaDevice(), "0");
} }
bool CudaPlatform::supportsDoublePrecision() const { bool CudaPlatform::supportsDoublePrecision() const {
return false; return false;
} }
const string& CudaPlatform::getPropertyValue(const Context& context, const string& property) const {
const ContextImpl& impl = getContextImpl(context);
const PlatformData* data = reinterpret_cast<const PlatformData*>(impl.getPlatformData());
map<string, string>::const_iterator value = data->propertyValues.find(property);
if (value != data->propertyValues.end())
return value->second;
return Platform::getPropertyValue(context, property);
}
void CudaPlatform::setPropertyValue(Context& context, const string& property, const string& value) const {
}
const StreamFactory& CudaPlatform::getDefaultStreamFactory() const { const StreamFactory& CudaPlatform::getDefaultStreamFactory() const {
return defaultStreamFactory; return defaultStreamFactory;
} }
void CudaPlatform::contextCreated(ContextImpl& context) const { void CudaPlatform::contextCreated(ContextImpl& context) const {
unsigned int device = 0;
const string& devicePropValue = getPropertyDefaultValue(CudaDevice());
if (devicePropValue.length() > 0)
stringstream(devicePropValue) >> device;
int numParticles = context.getSystem().getNumParticles(); int numParticles = context.getSystem().getNumParticles();
_gpuContext* gpu = (_gpuContext*) gpuInit(numParticles); _gpuContext* gpu = (_gpuContext*) gpuInit(numParticles, device);
context.setPlatformData(new PlatformData(gpu)); context.setPlatformData(new PlatformData(gpu));
} }
...@@ -77,3 +100,10 @@ void CudaPlatform::contextDestroyed(ContextImpl& context) const { ...@@ -77,3 +100,10 @@ void CudaPlatform::contextDestroyed(ContextImpl& context) const {
gpuShutDown(data->gpu); gpuShutDown(data->gpu);
delete data; delete data;
} }
CudaPlatform::PlatformData::PlatformData(_gpuContext* gpu) : gpu(gpu), removeCM(false), nonbondedMethod(0), hasBonds(false), hasAngles(false),
hasPeriodicTorsions(false), hasRB(false), hasNonbonded(false), primaryKernel(NULL), stepCount(0), computeForceCount(0), time(0.0) {
stringstream device;
device << gpu->device;
propertyValues[CudaPlatform::CudaDevice()] = device.str();
}
...@@ -1116,7 +1116,7 @@ bool gpuIsAvailable() ...@@ -1116,7 +1116,7 @@ bool gpuIsAvailable()
} }
extern "C" extern "C"
void* gpuInit(int numAtoms) void* gpuInit(int numAtoms, unsigned int device)
{ {
gpuContext gpu = new _gpuContext; gpuContext gpu = new _gpuContext;
int LRFSize = 0; int LRFSize = 0;
...@@ -1124,30 +1124,10 @@ void* gpuInit(int numAtoms) ...@@ -1124,30 +1124,10 @@ void* gpuInit(int numAtoms)
int SMMajor = 0; int SMMajor = 0;
int SMMinor = 0; int SMMinor = 0;
// Get adapter // Select which device to use
unsigned int device = 0; cudaSetDevice(device); // Ignore errors
char * pAdapter; cudaError_t status = cudaGetDevice(&gpu->device);
pAdapter = getenv ("NV_FAH_DEVICE"); RTERROR(status, "Error getting CUDA device")
if (pAdapter != NULL)
{
sscanf(pAdapter, "%d", &device);
}
// cudaError_t status = cudaSetDevice(device);
// RTERROR(status, "Error setting CUDA device")
// Determine which core to run on
#if 0
SYSTEM_INFO info;
GetSystemInfo(&info);
unsigned int cores = info.dwNumberOfProcessors;
if (cores > 1)
{
HANDLE hproc = GetCurrentProcess();
unsigned int core = (cores - 1) - (device % (cores - 1));
unsigned int mask = 1 << core;
SetProcessAffinityMask(hproc, mask);
}
#endif
// Determine kernel call configuration // Determine kernel call configuration
cudaDeviceProp deviceProp; cudaDeviceProp deviceProp;
......
...@@ -58,6 +58,7 @@ struct _gpuContext { ...@@ -58,6 +58,7 @@ struct _gpuContext {
//Cache this here so that it doesn't //Cache this here so that it doesn't
//have to be repeatedly passed around //have to be repeatedly passed around
int natoms; int natoms;
int device;
gpuAtomType* gpAtomTable; gpuAtomType* gpAtomTable;
int gAtomTypes; int gAtomTypes;
cudaGmxSimulation sim; cudaGmxSimulation sim;
...@@ -204,7 +205,7 @@ extern "C" ...@@ -204,7 +205,7 @@ extern "C"
void gpuInitializeRandoms(gpuContext gpu); void gpuInitializeRandoms(gpuContext gpu);
extern "C" extern "C"
void* gpuInit(int numAtoms); void* gpuInit(int numAtoms, unsigned int device);
extern "C" extern "C"
void gpuSetIntegrationParameters(gpuContext gpu, float tau, float deltaT, float temperature); void gpuSetIntegrationParameters(gpuContext gpu, float tau, float deltaT, float temperature);
......
...@@ -48,7 +48,7 @@ static const float RGAS = BOLTZMANN * AVOGADRO; // (J ...@@ -48,7 +48,7 @@ static const float RGAS = BOLTZMANN * AVOGADRO; // (J
static const float BOLTZ = (RGAS / KILO); // (kJ/(mol K)) static const float BOLTZ = (RGAS / KILO); // (kJ/(mol K))
void testGaussian() { void testGaussian() {
_gpuContext* gpu = (_gpuContext*) gpuInit(5000); _gpuContext* gpu = (_gpuContext*) gpuInit(5000, 0);
gpu->sim.Yv = 1.0; gpu->sim.Yv = 1.0;
gpu->sim.Yx = 1.0; gpu->sim.Yx = 1.0;
gpu->sim.V = 1.0; gpu->sim.V = 1.0;
......
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