forked from NVIDIA/cuda-quantum
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCuDensityMatSim.cpp
More file actions
176 lines (161 loc) · 6.62 KB
/
CuDensityMatSim.cpp
File metadata and controls
176 lines (161 loc) · 6.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*******************************************************************************
* Copyright (c) 2022 - 2026 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
* the terms of the Apache License 2.0 which accompanies this distribution. *
******************************************************************************/
#include "CircuitSimulator.h"
#include "CuDensityMatContext.h"
#include "CuDensityMatErrorHandling.h"
#include "CuDensityMatState.h"
#include "common/FmtCore.h"
#include "cudaq.h"
#include "cudaq/distributed/mpi_plugin.h"
namespace {
// Hook to query this shared lib file location at runtime.
extern "C" {
void cuDensityMatSimCppFileMarker() { return; }
}
/// @brief Query the full path to the this lib.
static const char *getThisSharedLibFilePath() {
static thread_local std::string LIB_PATH;
if (LIB_PATH.empty()) {
// Use dladdr query this .so file
void *funcPtrToFind = (void *)(intptr_t)cuDensityMatSimCppFileMarker;
Dl_info DLInfo;
int err = dladdr(funcPtrToFind, &DLInfo);
if (err != 0) {
char link_path[PATH_MAX];
// If the filename is a symlink, we need to resolve and return the
// location of the actual .so file.
if (realpath(DLInfo.dli_fname, link_path))
LIB_PATH = link_path;
}
}
return LIB_PATH.c_str();
}
/// @brief Retrieve the path to the plugin implementation
std::string getMpiPluginFilePath() {
auto mpiPlugin = cudaq::mpi::getMpiPlugin();
if (!mpiPlugin)
throw std::runtime_error("Failed to retrieve MPI plugin");
return mpiPlugin->getPluginPath();
}
void initCuDensityMatCommLib() {
// If CUDENSITYMAT_COMM_LIB environment variable is not set,
// use this builtin plugin shim (redirect MPI calls to CUDA-Q plugin)
if (std::getenv("CUDENSITYMAT_COMM_LIB") == nullptr) {
CUDAQ_INFO("Enabling cuDensityMat MPI without environment variable "
"CUDENSITYMAT_COMM_LIB. \nUse the builtin cuDensityMat "
"communicator lib from '{}' - CUDA-Q MPI plugin {}.",
getThisSharedLibFilePath(), getMpiPluginFilePath());
setenv("CUDENSITYMAT_COMM_LIB", getThisSharedLibFilePath(), 0);
}
}
class CuDensityMatSim : public nvqir::CircuitSimulatorBase<double> {
private:
static constexpr int INVALID_CUDA_DEVICE = -1;
protected:
using ScalarType = double;
using DataType = std::complex<double>;
using DataVector = std::vector<DataType>;
using nvqir::CircuitSimulatorBase<ScalarType>::tracker;
using nvqir::CircuitSimulatorBase<ScalarType>::nQubitsAllocated;
using nvqir::CircuitSimulatorBase<ScalarType>::stateDimension;
using nvqir::CircuitSimulatorBase<ScalarType>::calculateStateDim;
using nvqir::CircuitSimulatorBase<ScalarType>::gateToString;
using nvqir::CircuitSimulatorBase<ScalarType>::x;
using nvqir::CircuitSimulatorBase<ScalarType>::flushGateQueue;
using nvqir::CircuitSimulatorBase<ScalarType>::previousStateDimension;
using nvqir::CircuitSimulatorBase<ScalarType>::shouldObserveFromSampling;
using nvqir::CircuitSimulatorBase<ScalarType>::summaryData;
public:
/// @brief The constructor
CuDensityMatSim() {
int numDevices{0};
HANDLE_CUDA_ERROR(cudaGetDeviceCount(&numDevices));
int currentDevice = INVALID_CUDA_DEVICE;
HANDLE_CUDA_ERROR(cudaGetDevice(¤tDevice));
const int deviceId = cudaq::mpi::is_initialized()
? cudaq::mpi::rank() % numDevices
: currentDevice;
if (cudaq::mpi::is_initialized())
initCuDensityMatCommLib();
HANDLE_CUDA_ERROR(cudaSetDevice(deviceId));
// Enable CUDA mem pool
{
// Enable by default
const bool enableMemPool =
cudaq::getEnvBool("CUDAQ_ENABLE_MEMPOOL", true);
if (!enableMemPool) {
CUDAQ_INFO("Mempool is disabled.");
} else {
// Check if mempool is available
int device{0};
HANDLE_CUDA_ERROR(cudaGetDevice(&device));
int supported{0};
HANDLE_CUDA_ERROR(cudaDeviceGetAttribute(
&supported, cudaDevAttrMemoryPoolsSupported, device));
if (!supported) {
CUDAQ_INFO("Memory pools are unsupported on this GPU");
} else {
cudaMemPool_t memPool;
HANDLE_CUDA_ERROR(cudaDeviceGetDefaultMemPool(&memPool, device));
uint64_t uMax = UINT64_MAX;
HANDLE_CUDA_ERROR(cudaMemPoolSetAttribute(
memPool, cudaMemPoolAttrReleaseThreshold, &uMax));
}
}
}
}
/// The destructor
virtual ~CuDensityMatSim() {}
std::unique_ptr<cudaq::SimulationState> getSimulationState() override {
return std::make_unique<cudaq::CuDensityMatState>();
}
void finalizeExecutionContext(cudaq::ExecutionContext &context) override {
// Just check that the dynamics target was not invoked in gate simulation
// contexts.
if (context.name != "evolve")
throw std::runtime_error(fmt::format(
"[dynamics target] Execution context '{}' is not supported.",
context.name));
}
void addQubitToState() override {
throw std::runtime_error(
"[dynamics target] Quantum gate simulation is not supported.");
}
void deallocateStateImpl() override {
throw std::runtime_error(
"[dynamics target] Quantum gate simulation is not supported.");
}
bool measureQubit(const std::size_t qubitIdx) override {
throw std::runtime_error("[dynamics target] Quantum gate simulation is not "
"supported.");
return false;
}
void applyGate(const GateApplicationTask &task) override {
throw std::runtime_error(
"[dynamics target] Quantum gate simulation is not supported.");
}
void setToZeroState() override {
throw std::runtime_error(
"[dynamics target] Quantum gate simulation is not supported.");
}
void resetQubit(const std::size_t qubitIdx) override {
throw std::runtime_error(
"[dynamics target] Quantum gate simulation is not supported.");
}
cudaq::ExecutionResult sample(const std::vector<std::size_t> &qubitIdxs,
const int shots,
bool includeSequentialData = true) override {
throw std::runtime_error("[dynamics target] Quantum gate simulation is not "
"supported.");
return cudaq::ExecutionResult();
}
std::string name() const override { return "dynamics"; }
NVQIR_SIMULATOR_CLONE_IMPL(CuDensityMatSim)
};
} // namespace
NVQIR_REGISTER_SIMULATOR(CuDensityMatSim, dynamics)