Maestro 0.3.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
DistributedMpiGpuLibrary.h
Go to the documentation of this file.
1// MPI remains behind the plugin C ABI; the application owns its lifecycle.
2#pragma once
3#ifdef __linux__
5#include <vector>
6
7namespace Simulators
8{
9class DistributedMpiGpuLibrary : public DistributedGpuLibrary
10{
11 public:
12 using Communicator = DistributedGpuApi::MgdMpiCommunicator;
13 using RuntimeInfo = DistributedGpuApi::MgdMpiRuntimeInfo;
14 static std::shared_ptr<DistributedMpiGpuLibrary> GetInstance();
15
16 void *CreateNative(int, int) override
17 {
18 throw std::logic_error("MPI GPU states require a communicator");
19 }
20
21 RuntimeInfo GetRuntimeInfo(const Communicator *comm)
22 {
23 std::lock_guard<std::recursive_mutex> lock(mutex);
24 RequireRuntime();
25 RuntimeInfo info{sizeof(RuntimeInfo), 0, 0, 0};
26 Check(getInfo(comm, &info), "GetMpiRuntimeInfo");
27 return info;
28 }
29
30 void GatherDevices(const Communicator *comm, int32_t device, std::vector<int32_t> &devices)
31 {
32 std::lock_guard<std::recursive_mutex> lock(mutex);
33 RequireRuntime();
34 Check(gather(comm, device, devices.data(), devices.size()), "GatherMpiDevices");
35 }
36
37 uint64_t GenerateSeed(const Communicator *comm)
38 {
39 std::lock_guard<std::recursive_mutex> lock(mutex);
40 RequireRuntime();
41 // Resolve on demand so explicit-seed execution also supports older plugins.
42 if (!generateSeed)
43 generateSeed = Resolve<decltype(generateSeed)>("GenerateMpiSeed");
44 uint64_t seed = 0;
45 Check(generateSeed(comm, &seed), "GenerateMpiSeed");
46 return seed;
47 }
48
49 void *CreateMpiNative(const Communicator *comm, int device, unsigned p2pBits)
50 {
51 std::lock_guard<std::recursive_mutex> lock(mutex);
52 RequireRuntime();
53 if (!initializationAttempted)
54 {
55 initializationAttempted = true;
56 if (validate(comm, std::getenv("MAESTRO_LICENSE_KEY")) != 1)
57 {
58 const char *detail = GetLastError();
59 initializationError = detail && *detail ? detail : "license validation failed";
60 throw std::runtime_error("MPI GPU backend unavailable: " + initializationError);
61 }
62 context = InitLib();
63 if (!context)
64 {
65 const char *detail = GetLastError();
66 initializationError = detail && *detail ? detail : "InitLib failed";
67 }
68 }
69 // Every rank enters, even when InitLib returned null. This agrees on
70 // library availability before any vendor collective construction.
71 auto obj = create(context, comm, device, p2pBits);
72 if (!obj)
73 {
74 if (!initializationError.empty())
75 throw std::runtime_error("MPI GPU backend unavailable: " + initializationError);
76 Fail("CreateMpiStateVectorRuntime");
77 }
78 ++liveStates;
79 return obj;
80 }
81
82 // Explicit terminal shutdown, after all states and before MPI_Finalize.
83 void FinalizeBackend()
84 {
85 std::lock_guard<std::recursive_mutex> lock(mutex);
86 if (liveStates != 0)
87 throw std::logic_error("Destroy all MPI GPU states before finalizing the backend");
88 if (finalized)
89 return;
90 if (context)
91 {
92 RequireRuntime();
93 Check(finalize(), "FinalizeMpiBackend");
94 }
95 finalized = true;
96 }
97
98 private:
99 DistributedMpiGpuLibrary() : DistributedGpuLibrary(true)
100 {
101 }
102
103 template <typename T> T Resolve(const char *name)
104 {
105 auto fn = reinterpret_cast<T>(GetFunction(name));
106 if (!fn)
107 throw std::runtime_error(std::string("MPI GPU plugin missing ") + name + "; update maestro-gpu-distributed");
108 return fn;
109 }
110
111 void RequireRuntime()
112 {
113 if (finalized)
114 throw std::runtime_error("MPI GPU backend is finalized");
115 RequireLoaded();
116 if (runtimeLoaded)
117 return;
118 getInfo = Resolve<decltype(getInfo)>("GetMpiRuntimeInfo");
119 gather = Resolve<decltype(gather)>("GatherMpiDevices");
120 validate = Resolve<decltype(validate)>("ValidateMpiLicenseRuntime");
121 create = Resolve<decltype(create)>("CreateMpiStateVectorRuntime");
122 finalize = Resolve<decltype(finalize)>("FinalizeMpiBackend");
123 runtimeLoaded = true;
124 }
125
126 int (*getInfo)(const Communicator *, RuntimeInfo *) = nullptr;
127 int (*gather)(const Communicator *, int32_t, int32_t *, uint32_t) = nullptr;
128 int (*generateSeed)(const Communicator *, uint64_t *) = nullptr;
129 int (*validate)(const Communicator *, const char *) = nullptr;
130 void *(*create)(void *, const Communicator *, int32_t, uint32_t) = nullptr;
131 int (*finalize)() = nullptr;
132 bool finalized = false, runtimeLoaded = false;
133 bool initializationAttempted = false;
134 std::string initializationError;
135};
136} // namespace Simulators
137#endif
Bounded online routing based on current physical bond dimensions.