System
Core system configuration and initialization module for UAMMD.
System is UAMMD’s core module responsible for interfacing with the machine the software is running on. It handles things like CUDA initialization, command line argument parsing, and provides a logging system. System is the first module to be initialized when UAMMD starts, and the last one to be finalized.
Note
System is automatically created by ParticleData when not provided by the user. Most times you will not need to create a System object manually.
-
class System
The central runtime manager for CUDA-based UAMMD simulations.
Note
Most of the time you do not need to handle the creation of ::System. ::ParticleData will auto initialize it for you if you do not provide one. You can request ::ParticleData for a reference to ::System with ::ParticleData::getSystem(). ::System should be created explicitly if the user wants to provide command line arguments.
Public Functions
-
inline System()
Construct a System object with no command-line arguments.
This initializes the system with default values, prepares the CUDA backend, sets up logging, seeds the random number generator, and performs device capability checks.
-
inline System(int argc, char *argv[])
Construct a System object using command-line arguments.
Parses
argvto extract optional parameters like--device. Initializes the CUDA environment accordingly, performs logging setup, seeds the RNG, and checks device compatibility.- Parameters:
argc – Argument count.
argv – Argument vector.
-
inline void finish()
Destructor for System.
Cleans up resources, synchronizes the device, and prints a farewell message.
-
inline Xorshift128plus &rng()
Get the random number generator used by the system.
This returns a reference to the Xorshift128plus random number generator used throughout UAMMD for generating random numbers (or seeding other generators).
-
inline const char **getargv() const
Get the command-line arguments System was initialized with.
This returns a pointer to the array of command-line arguments. The arguments are stored as
char*pointers, so you can access them as C-style strings.
-
inline const SystemParameters getSystemParameters() const
Get the system parameters.
This returns a reference to the SystemParameters struct, which contains information about the CUDA device, compute capability, and managed memory availability.
Public Static Functions
-
template<int level, class ...T>
static inline void log(char const *fmt, T... args) Log a message at a specific log level.
See the Logging section for more details on logging levels.
-
template<int level>
static inline void log(const std::string &msg) Log a message at a specific log level using a string.
This is a convenience function that allows logging messages using a std::string instead of a format string.
-
template<class T = char>
static inline allocator<T> getTemporaryDeviceAllocator() Get the default device memory resource.
This returns an cached CUDA memory allocator that can be used to quickly allocate temporary memory.
See the Cached memory allocation section for more details on memory management in UAMMD.
- Template Parameters:
T – The type of the allocator, defaults to char.
- Returns:
An allocator that can be used to allocate memory on the device.
-
inline System()
-
struct SystemParameters
Holds system parameters for the UAMMD simulation.
Hint
System (or ParticleData) should be the first thing to create in a UAMMD simulation code, see any of the examples in examples folder.
Example: creating a System instance
...
int main(int argc, char *argv[]){
auto sys = std::make_shared<System>(argc, argv);
//You may seed the rng algorithm here. The default seed is obtained from time(NULL).
sys->rng().setSeed(time(NULL));
...
//If we initialize System, ParticleData has to be provided with the same instance
int N = 10000; //An arbitrary number of particles
auto pd = std::make_shared<ParticleData>(N, sys);
//This will ensure the termination of any UAMMD related operation.
sys->finish();
return 0;
}
Utilities provided by System
Random numbers
You can access a Xorshift128plus random generator from System. This generator should be used for things like seeding other generators, maybe creating initial configurations.
-
Xorshift128plus &System::rng();
Returns a reference to the System’s random number generator.
...
//Set the seed of the rng
sys->rng().setSeed(123124);
//Get a random integer between 0 and 2^64-1
uint64_t Z64 = sys->rng().next();
//Get a random integer between 0 and 2^32-1
uint32_t Z32 = sys->rng().next32();
//Get a uniform number between a and b
double a=0, b=1;
double Zf = sys->rng().uniform(a,b);
//Get a gaussian number with mean a and std b
double Zg = sys->rng().gaussian(a,b);
...
Logging
System provides a logging engine with several levels of relevance for the message via the System::log method. The log level is set at compile time via the preprocessor macro MAXLOGLEVEL, which can be set to any value between 0 and 13. The higher the value, the more verbose the logging will be. See Compiling UAMMD. The levels are:
-
enum uammd::System::LogLevel
Defines the logging levels used in UAMMD.
Values:
-
enumerator CRITICAL
-
enumerator ERROR
-
enumerator EXCEPTION
-
enumerator WARNING
-
enumerator MESSAGE
-
enumerator STDERR
-
enumerator STDOUT
-
enumerator DEBUG
-
enumerator DEBUG1
-
enumerator DEBUG2
-
enumerator DEBUG3
-
enumerator DEBUG4
-
enumerator DEBUG5
-
enumerator DEBUG6
-
enumerator DEBUG7
-
enumerator CRITICAL
Example:
System::log<System::CRITICAL>("The program will be terminated after printing this message!");
System::log<System::ERROR>("There was an error, but I might be able to circumvent it!");
System::log<System::WARNING>("Something happen that might be problematic, watch out! (I will keep running OK though)");
System::log<System::MESSAGE>("Here you have some useful information I want you to know!");
System::log<System::STDERR>("This goes straight to stderr");
System::log<System::STDOUT>("This goes straight to stdout");
System::log<System::DEBUG>("A debug message!");
System::log<System::DEBUG1>("A more internal debug message!");
...
System::log<System::DEBUG7>("There are 7 levels of debug!");
Cached memory allocation
UAMMD exposes a cached allocator of GPU memory via System under the names System::allocator<T> and System::allocator_thrust<T>. Both types comply with the C++ standard library’s Allocator concept and can thus be used with the standard library’s containers, such as std::vector.
-
template<class T>
class System::allocator An std-compatible polymorphic pool allocator that provides GPU memory (allocated via cudaMalloc). Allocations via this type will be cached. If a chunk of memory is allocated and deallocated, the next time a similar chunk is requested will not incur in a cudaMalloc call.
-
template<class T>
class System::thrust_allocator Thurst containers require an allocator with a pointer type
thrust::device_ptr<T>(instead of the plain T* provided bySystem::allocator<T>). This type behaves identical toSystem::allocator<T>(and shares its memory pool) but can be used with thrust containers.
Hint
System’s allocators normally work with GPU global memory, but turn to managed memory if UAMMD_DEBUG is defined.
Usage example:
#include"uammd.cuh"
#include<thrust/device_vector.h>
#include<memory>
#include<vector>
using namespace uammd;
int main(){
//Note that System's allocator functionality are provided via static calls, an actual instance is not needed. But a System being initialized somewhere will help.
auto sys = std::make_shared<System>();
//Only the first iteration incurs a cudaMalloc, and cudaFree is called only when System::finish() is called.
for(int i = 0; i<10; i++){
thrust::device_vector<char, System::allocator_thrust<char>> vec;
vec.resize(10000);
}
//You can interchange with a thrust vector using the default allocator.
{
thrust::device_vector<char, System::allocator_thrust<char>> vec;
vec.resize(10000);
thrust::device_vector<char> device_copy_with_default_allocator(vec);
}
{
//Using the allocator with a shared_ptr.
std::shared_ptr<int> temp;
//Note that this is a static method, a System instance is not actually needed.
//A default global instance of the allocator is returned.
auto alloc = sys->getTemporaryDeviceAllocator<int>();
temp = std::shared_ptr<int>(alloc.allocate(1000),
[=](int* ptr){alloc.deallocate(ptr);});
}
sys->finish();
return 0;
}
System options
Here is a list of flags accepted by System
–device X : UAMMD will run in the GPU with number X.
–increase_print_limit X : CUDA’s printf limit will be increased to X.