.. _program_listing_file_include_flamegpu_simulation_CUDASimulation.h: Program Listing for File CUDASimulation.h ========================================= |exhale_lsh| :ref:`Return to documentation for file ` (``include/flamegpu/simulation/CUDASimulation.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef INCLUDE_FLAMEGPU_SIMULATION_CUDASIMULATION_H_ #define INCLUDE_FLAMEGPU_SIMULATION_CUDASIMULATION_H_ #include #include #include #include #include #include #include #include #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> CUDAAgentMap; typedef std::unordered_map> CUDAMessageMap; typedef std::map> CUDASubModelMap; typedef std::unordered_map> 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 &model, bool _isSWIG); CUDASimulation(const std::shared_ptr& 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 void setEnvironmentProperty(const std::string &property_name, T value); template void setEnvironmentProperty(const std::string &property_name, const std::array &value); template void setEnvironmentProperty(const std::string& property_name, flamegpu::size_type index, T value); #ifdef SWIG template void setEnvironmentPropertyArray(const std::string& property_name, const std::vector& value); #endif template T getEnvironmentProperty(const std::string &property_name); template std::array getEnvironmentProperty(const std::string &property_name); template T getEnvironmentProperty(const std::string& property_name, flamegpu::size_type index); #ifdef SWIG template std::vector 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 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 elapsedSecondsPerStep; void incrementStepCounter(); CUDAAgentMap agent_map; std::shared_ptr macro_env; CUDADirectedGraphMap directed_graph_map; Config config; std::shared_ptr step_log_config; std::shared_ptr exit_log_config; std::unique_ptr run_log; void resetLog(); void processStepLog(const double step_time_seconds); void processExitLog(); CUDAMessageMap message_map; CUDASubModelMap submodel_map; std::vector streams; void createStreams(const unsigned int nStreams); cudaStream_t getStream(const unsigned int n); void destroyStreams(); void synchronizeAllStreams(); void stepLayer(const std::shared_ptr& layer, const unsigned int layerIndex); void layerHostFunctions(const std::shared_ptr& 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 sortTriggers2D; std::set sortTriggers3D; void determineAgentsToSort(); struct Singletons { detail::RandomManager rng; detail::CUDAScatter scatter; std::shared_ptr environment; detail::DeviceStrings strings; #if !defined(FLAMEGPU_SEATBELTS) || FLAMEGPU_SEATBELTS exception::DeviceExceptionManager exception; #endif explicit Singletons(const std::shared_ptr &environment) : environment(environment) { } } * singletons; void initEnvironmentMgr(); void initMacroEnvironment(); bool singletonsInitialised; bool rtcInitialised; int deviceInitialised = -1; void initialiseSingletons(); void initialiseRTC(); std::unique_ptr host_api; void processHostAgentCreation(unsigned int streamId); public: typedef std::vector AgentDataBuffer; typedef std::unordered_map AgentDataBufferStateMap; typedef std::unordered_map AgentOffsetMap; typedef std::unordered_map AgentDataMap; private: std::shared_ptr getEnvironment() const override; std::shared_ptr getMacroEnvironment() const override; void assignAgentIDs(); bool agent_ids_have_init = true; AgentOffsetMap agentOffsets; AgentDataMap agentData; void initOffsetsAndMap(); #ifdef FLAMEGPU_VISUALISATION std::shared_ptr visualisation; #endif static bool detectPureRTC(const std::shared_ptr& _model); #if __CUDACC_VER_MAJOR__ >= 12 std::uint64_t cudaContextID; #endif // __CUDACC_VER_MAJOR__ >= 12 protected: const bool isPureRTC; const bool isSWIG; }; template 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(property_name, value); } template void CUDASimulation::setEnvironmentProperty(const std::string& property_name, const std::array& 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(property_name, value); } template void CUDASimulation::setEnvironmentProperty(const std::string& property_name, const flamegpu::size_type index, const T value) { if (!singletonsInitialised) initialiseSingletons(); singletons->environment->setProperty(property_name, index, value); } template T CUDASimulation::getEnvironmentProperty(const std::string& property_name) { if (!singletonsInitialised) initialiseSingletons(); return singletons->environment->getProperty(property_name); } template std::array CUDASimulation::getEnvironmentProperty(const std::string& property_name) { if (!singletonsInitialised) initialiseSingletons(); return singletons->environment->getProperty(property_name); } template T CUDASimulation::getEnvironmentProperty(const std::string& property_name, const flamegpu::size_type index) { if (!singletonsInitialised) initialiseSingletons(); return singletons->environment->getProperty(property_name, index); } #ifdef SWIG template void CUDASimulation::setEnvironmentPropertyArray(const std::string& property_name, const std::vector& 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(property_name, value); } template std::vector CUDASimulation::getEnvironmentPropertyArray(const std::string& property_name) { if (!singletonsInitialised) initialiseSingletons(); return singletons->environment->getPropertyArray(property_name); } #endif } // namespace flamegpu #endif // INCLUDE_FLAMEGPU_SIMULATION_CUDASIMULATION_H_