Program Listing for File CUDASimulation.h
↰ Return to documentation for file (include/flamegpu/simulation/CUDASimulation.h
)
#ifndef INCLUDE_FLAMEGPU_SIMULATION_CUDASIMULATION_H_
#define INCLUDE_FLAMEGPU_SIMULATION_CUDASIMULATION_H_
#include <cuda.h>
#include <atomic>
#include <memory>
#include <vector>
#include <string>
#include <unordered_map>
#include <map>
#include <set>
#include "flamegpu/exception/FLAMEGPUDeviceException.cuh"
#include "flamegpu/simulation/Simulation.h"
#include "flamegpu/runtime/detail/curve/HostCurve.cuh"
#include "flamegpu/simulation/detail/CUDAScatter.cuh"
#include "flamegpu/simulation/CUDAEnsemble.h"
#include "flamegpu/simulation/detail/RandomManager.cuh"
#include "flamegpu/runtime/agent/HostNewAgentAPI.h"
#include "flamegpu/simulation/detail/CUDAMacroEnvironment.h"
#include "flamegpu/simulation/detail/EnvironmentManager.cuh"
#include "flamegpu/simulation/detail/DeviceStrings.h"
#include "flamegpu/simulation/detail/CUDAEnvironmentDirectedGraphBuffers.cuh"
#ifdef FLAMEGPU_VISUALISATION
#include "flamegpu/visualiser/ModelVis.h"
#endif
#ifdef _MSC_VER
#pragma warning(push, 2)
#include "jitify/jitify.hpp"
#pragma warning(pop)
#else
#include "jitify/jitify.hpp"
#endif
namespace flamegpu {
namespace detail {
class AbstractSimRunner;
class CUDAAgent;
class CUDAMessage;
} // namespace detail
class AgentVector;
class LoggingConfig;
class StepLoggingConfig;
class RunPlan;
struct RunLog;
class CUDASimulation : public Simulation {
friend class HostAgentAPI;
friend class HostAPI;
friend class detail::AbstractSimRunner;
friend class CUDAEnsemble;
#ifdef FLAMEGPU_VISUALISATION
friend class visualiser::ModelVis;
friend struct visualiser::ModelVisData;
#endif
typedef std::unordered_map<std::string, std::unique_ptr<detail::CUDAAgent>> CUDAAgentMap;
typedef std::unordered_map<std::string, std::unique_ptr<detail::CUDAMessage>> CUDAMessageMap;
typedef std::map<std::string, std::unique_ptr<CUDASimulation>> CUDASubModelMap;
typedef std::unordered_map<std::string, std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers>> CUDADirectedGraphMap;
public:
struct Config {
friend class detail::AbstractSimRunner;
friend class CUDASimulation;
friend class HostAPI;
int device_id = 0;
bool inLayerConcurrency = true;
private:
bool is_submodel = false;
bool is_ensemble = false;
unsigned int ensemble_run_id = UINT_MAX;
};
explicit CUDASimulation(const ModelDescription& model, int argc = 0, const char** argv = nullptr)
#ifdef SWIG
: CUDASimulation(model, argc, argv, true)
#else
: CUDASimulation(model, argc, argv, false)
#endif
{ }
private:
CUDASimulation(const ModelDescription& model, int argc, const char** argv, bool _isSWIG);
CUDASimulation(const std::shared_ptr<const ModelData> &model, bool _isSWIG);
CUDASimulation(const std::shared_ptr<SubModelData>& submodel_desc, CUDASimulation *master_model);
public:
virtual ~CUDASimulation();
void initFunctions() override;
bool step() override;
void exitFunctions() override;
void simulate() override;
void simulate(const RunPlan &plan);
void setPopulationData(AgentVector& population, const std::string &state_name = ModelData::DEFAULT_STATE) override;
void getPopulationData(AgentVector& population, const std::string& state_name = ModelData::DEFAULT_STATE) override;
template<typename T>
void setEnvironmentProperty(const std::string &property_name, T value);
template<typename T, flamegpu::size_type N>
void setEnvironmentProperty(const std::string &property_name, const std::array<T, N> &value);
template<typename T, flamegpu::size_type N = 0>
void setEnvironmentProperty(const std::string& property_name, flamegpu::size_type index, T value);
#ifdef SWIG
template<typename T>
void setEnvironmentPropertyArray(const std::string& property_name, const std::vector<T>& value);
#endif
template<typename T>
T getEnvironmentProperty(const std::string &property_name);
template<typename T, flamegpu::size_type N>
std::array<T, N> getEnvironmentProperty(const std::string &property_name);
template<typename T, flamegpu::size_type N = 0>
T getEnvironmentProperty(const std::string& property_name, flamegpu::size_type index);
#ifdef SWIG
template<typename T>
std::vector<T> getEnvironmentPropertyArray(const std::string& property_name);
#endif
Config &CUDAConfig();
unsigned int getStepCounter() override;
void resetStepCounter() override;
const Config &getCUDAConfig() const;
void setStepLog(const StepLoggingConfig &stepConfig);
void setExitLog(const LoggingConfig &exitConfig);
const RunLog &getRunLog() const override;
#ifdef FLAMEGPU_VISUALISATION
visualiser::ModelVis getVisualisation();
#endif
double getElapsedTimeRTCInitialisation() const;
double getElapsedTimeSimulation() const;
double getElapsedTimeInitFunctions() const;
double getElapsedTimeExitFunctions() const;
std::vector<double> getElapsedTimeSteps() const;
double getElapsedTimeStep(unsigned int step) const;
using Simulation::getInstanceID;
protected:
void reset(bool submodelReset) override;
void applyConfig_derived() override;
bool checkArgs_derived(int argc, const char** argv, int &i) override;
void printHelp_derived() override;
private:
detail::CUDAAgent& getCUDAAgent(const std::string& agent_name) const;
detail::CUDAMessage& getCUDAMessage(const std::string& message_name) const;
void reseed(uint64_t seed);
unsigned int step_count;
double elapsedSecondsSimulation;
double elapsedSecondsInitFunctions;
double elapsedSecondsExitFunctions;
double elapsedSecondsRTCInitialisation;
std::vector<double> elapsedSecondsPerStep;
void incrementStepCounter();
CUDAAgentMap agent_map;
std::shared_ptr<detail::CUDAMacroEnvironment> macro_env;
CUDADirectedGraphMap directed_graph_map;
Config config;
std::shared_ptr<const StepLoggingConfig> step_log_config;
std::shared_ptr<const LoggingConfig> exit_log_config;
std::unique_ptr<RunLog> run_log;
void resetLog();
void processStepLog(const double step_time_seconds);
void processExitLog();
CUDAMessageMap message_map;
CUDASubModelMap submodel_map;
std::vector<cudaStream_t> streams;
void createStreams(const unsigned int nStreams);
cudaStream_t getStream(const unsigned int n);
void destroyStreams();
void synchronizeAllStreams();
void stepLayer(const std::shared_ptr<LayerData>& layer, const unsigned int layerIndex);
void layerHostFunctions(const std::shared_ptr<LayerData>& layer, const unsigned int layerIndex);
void stepStepFunctions();
bool stepExitConditions();
void spatialSortAgent_async(const std::string& funcName, const std::string& agentName, const std::string& state, const int mode, cudaStream_t stream, unsigned int streamId);
constexpr static int Agent2D = 0;
constexpr static int Agent3D = 1;
std::set<std::string> sortTriggers2D;
std::set<std::string> sortTriggers3D;
void determineAgentsToSort();
struct Singletons {
detail::RandomManager rng;
detail::CUDAScatter scatter;
std::shared_ptr<detail::EnvironmentManager> environment;
detail::DeviceStrings strings;
#if !defined(FLAMEGPU_SEATBELTS) || FLAMEGPU_SEATBELTS
exception::DeviceExceptionManager exception;
#endif
explicit Singletons(const std::shared_ptr<detail::EnvironmentManager> &environment) : environment(environment) { }
} * singletons;
void initEnvironmentMgr();
void initMacroEnvironment();
bool singletonsInitialised;
bool rtcInitialised;
int deviceInitialised = -1;
void initialiseSingletons();
void initialiseRTC();
std::unique_ptr<HostAPI> host_api;
void processHostAgentCreation(unsigned int streamId);
public:
typedef std::vector<NewAgentStorage> AgentDataBuffer;
typedef std::unordered_map<std::string, AgentDataBuffer> AgentDataBufferStateMap;
typedef std::unordered_map<std::string, VarOffsetStruct> AgentOffsetMap;
typedef std::unordered_map<std::string, AgentDataBufferStateMap> AgentDataMap;
private:
std::shared_ptr<detail::EnvironmentManager> getEnvironment() const override;
std::shared_ptr<const detail::CUDAMacroEnvironment> getMacroEnvironment() const override;
void assignAgentIDs();
bool agent_ids_have_init = true;
AgentOffsetMap agentOffsets;
AgentDataMap agentData;
void initOffsetsAndMap();
#ifdef FLAMEGPU_VISUALISATION
std::shared_ptr<visualiser::ModelVisData> visualisation;
#endif
static bool detectPureRTC(const std::shared_ptr<const ModelData>& _model);
#if __CUDACC_VER_MAJOR__ >= 12
std::uint64_t cudaContextID;
#endif // __CUDACC_VER_MAJOR__ >= 12
protected:
const bool isPureRTC;
const bool isSWIG;
};
template<typename T>
void CUDASimulation::setEnvironmentProperty(const std::string& property_name, const T value) {
if (!property_name.empty() && property_name[0] == '_') {
THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, "
"in CUDASimulation::setEnvironmentProperty().");
}
if (!singletonsInitialised)
initialiseSingletons();
singletons->environment->setProperty<T>(property_name, value);
}
template<typename T, flamegpu::size_type N>
void CUDASimulation::setEnvironmentProperty(const std::string& property_name, const std::array<T, N>& value) {
if (!property_name.empty() && property_name[0] == '_') {
THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, "
"in CUDASimulation::setEnvironmentProperty().");
}
if (!singletonsInitialised)
initialiseSingletons();
singletons->environment->setProperty<T, N>(property_name, value);
}
template<typename T, flamegpu::size_type N>
void CUDASimulation::setEnvironmentProperty(const std::string& property_name, const flamegpu::size_type index, const T value) {
if (!singletonsInitialised)
initialiseSingletons();
singletons->environment->setProperty<T, N>(property_name, index, value);
}
template<typename T>
T CUDASimulation::getEnvironmentProperty(const std::string& property_name) {
if (!singletonsInitialised)
initialiseSingletons();
return singletons->environment->getProperty<T>(property_name);
}
template<typename T, flamegpu::size_type N>
std::array<T, N> CUDASimulation::getEnvironmentProperty(const std::string& property_name) {
if (!singletonsInitialised)
initialiseSingletons();
return singletons->environment->getProperty<T, N>(property_name);
}
template<typename T, flamegpu::size_type N>
T CUDASimulation::getEnvironmentProperty(const std::string& property_name, const flamegpu::size_type index) {
if (!singletonsInitialised)
initialiseSingletons();
return singletons->environment->getProperty<T, N>(property_name, index);
}
#ifdef SWIG
template<typename T>
void CUDASimulation::setEnvironmentPropertyArray(const std::string& property_name, const std::vector<T>& value) {
if (!property_name.empty() && property_name[0] == '_') {
THROW exception::ReservedName("Environment property names cannot begin with '_', this is reserved for internal usage, "
"in CUDASimulation::setEnvironmentPropertyArray().");
}
if (!singletonsInitialised)
initialiseSingletons();
singletons->environment->setPropertyArray<T>(property_name, value);
}
template<typename T>
std::vector<T> CUDASimulation::getEnvironmentPropertyArray(const std::string& property_name) {
if (!singletonsInitialised)
initialiseSingletons();
return singletons->environment->getPropertyArray<T>(property_name);
}
#endif
} // namespace flamegpu
#endif // INCLUDE_FLAMEGPU_SIMULATION_CUDASIMULATION_H_