Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
common_DFE.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:13:26 2020
3 Copyright 2020 Peter Rakyta, Ph.D.
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 
17 @author: Peter Rakyta, Ph.D.
18 */
24 #include "common_DFE.h"
25 #include "matrix_base.hpp"
26 
27 #include <atomic>
28 #include <dlfcn.h>
29 #include <unistd.h>
30 #include <mutex>
31 
32 
33 // pointer to the dynamically loaded DFE library
34 void* handle = NULL;
35 
37 std::atomic_size_t read_count(0); //readers-writer problem semaphore
38 
40 std::recursive_mutex libmutex; //writing mutex
41 std::mutex libreadmutex; //reader mutex
42 
43 
44 extern "C" {
45 
46 size_t (*get_accelerator_avail_num_dll)() = NULL;
47 size_t (*get_accelerator_free_num_dll)() = NULL;
48 int (*calcqgdKernelDFE_dll)(size_t rows, size_t cols, DFEgate_kernel_type* gates, int gatesNum, int gateSetNum, int traceOffset, double* trace) = NULL;
49 int (*load2LMEM_dll)(QGD_Complex16* data, size_t rows, size_t cols) = NULL;
50 void (*releive_DFE_dll)() = NULL;
51 int (*initialize_DFE_dll)( int accelerator_num ) = NULL;
53 
54 }
55 
56 // The ID of the class that has initialized the accelerator lib (used to not initialze again if not necessary)
57 int initialize_id = -1;
58 
59 
60 
65 void uploadMatrix2DFE( Matrix& input ) {
66 
67  std::cout << "size in bytes of uploading to DFE: " << input.size()*2*sizeof(float) << std::endl;
68 
69  // load the data to LMEM
70  if (load2LMEM_dll( input.get_data(), input.rows, input.cols )) initialize_id = -1;
71 
72 }
73 
74 
79 {
80  const std::lock_guard<std::recursive_mutex> lock(libmutex);
81  if (handle) {
83  dlclose(handle);
84  handle = NULL;
85  }
86 }
87 
88 
89 
90 
91 
92 
93 
101 int init_dfe_lib( const int accelerator_num, int qbit_num, int initialize_id_in ) {
102 
103  const std::lock_guard<std::recursive_mutex> lock(libmutex);
104 
105  initialize_id = initialize_id_in;
106 
107 
108  unload_dfe_lib();
109 
110 
111  std::string lib_name_DFE = qbit_num > 9 ? DFE_LIB_10QUBITS : DFE_LIB_9QUBITS;
112  std::string lib_name = getenv("SLIC_CONF") ? DFE_LIB_SIM : lib_name_DFE;
113 
114  // dynamic-loading the correct DFE permanent calculator (Simulator/DFE/single or dual) from shared libararies
115  handle = dlopen(lib_name.c_str(), RTLD_NOW); //"MAXELEROSDIR"
116  if (handle == NULL && qbit_num == 10 && !getenv("SLIC_CONF")) {
117  handle = dlopen(DFE_LIB_9QUBITS, RTLD_NOW);
118  }
119  if (handle == NULL) {
120  initialize_id = -1;
121  std::string err("init_dfe_lib: failed to load library " + lib_name + " - " + std::string(dlerror()));
122  throw err;
123  }
124  else {
125 
126  get_accelerator_avail_num_dll = (size_t (*)())dlsym(handle, "get_accelerator_avail_num");
127  get_accelerator_free_num_dll = (size_t (*)())dlsym(handle, "get_accelerator_free_num");
128  calcqgdKernelDFE_dll = (int (*)(size_t, size_t, DFEgate_kernel_type*, int, int, int, double*))dlsym(handle, "calcqgdKernelDFE");
129  load2LMEM_dll = (int (*)(QGD_Complex16*, size_t, size_t))dlsym(handle, "load2LMEM");
130  releive_DFE_dll = (void (*)())dlsym(handle, "releive_DFE");
131  initialize_DFE_dll = (int (*)(int))dlsym(handle, "initialize_DFE");
132  get_chained_gates_num_dll = (int (*)())dlsym(handle, "get_chained_gates_num");
133 
134  if (initialize_DFE_dll(accelerator_num)) initialize_id = -1;
135 
136  }
137  return initialize_id;
138 
139 }
140 
141 
145 void lock_lib()
146 {
147  const std::lock_guard<std::mutex> lock(libreadmutex);
148  if (++read_count == 1) libmutex.lock();
149 }
150 
151 
156 {
157  const std::lock_guard<std::mutex> lock(libreadmutex);
158  if (--read_count == 0) libmutex.unlock();
159 }
160 
161 
162 
163 
164 
170 
172 
173 }
174 
175 
181 
183 
184 }
185 
191 
192  return initialize_id;
193 
194 }
195 
207 int calcqgdKernelDFE(size_t rows, size_t cols, DFEgate_kernel_type* gates, int gatesNum, int gateSetNum, int traceOffset, double* trace) {
208 
209 
210  return calcqgdKernelDFE_dll(rows, cols, gates, gatesNum, gateSetNum, traceOffset, trace);
211 
212 }
213 
214 
215 
221 
222  return get_chained_gates_num_dll();
223 
224 }
225 
226 
int get_chained_gates_num()
Call to retrieve the number of gates that should be chained up during the execution of the DFE librar...
Definition: common_DFE.cpp:220
int(* load2LMEM_dll)(QGD_Complex16 *data, size_t rows, size_t cols)
Definition: common_DFE.cpp:49
std::mutex libreadmutex
Definition: common_DFE.cpp:41
void * handle
Definition: common_DFE.cpp:34
void lock_lib()
Call to lock the access to the execution of the DFE library.
Definition: common_DFE.cpp:145
void(* releive_DFE_dll)()
Definition: common_DFE.cpp:50
void uploadMatrix2DFE(Matrix &input)
Call to upload the input matrix to the DFE engine.
Definition: common_DFE.cpp:65
data
load the unitary from file
Definition: example.py:51
int(* initialize_DFE_dll)(int accelerator_num)
Definition: common_DFE.cpp:51
scalar * get_data() const
Call to get the pointer to the stored data.
void unlock_lib()
Call to unlock the access to the execution of the DFE library.
Definition: common_DFE.cpp:155
int init_dfe_lib(const int accelerator_num, int qbit_num, int initialize_id_in)
Call to initialize the DFE library support and allocate the requested devices.
Definition: common_DFE.cpp:101
int rows
The number of rows.
Definition: matrix_base.hpp:42
int cols
The number of columns.
Definition: matrix_base.hpp:44
size_t(* get_accelerator_avail_num_dll)()
Definition: common_DFE.cpp:46
#define DFE_LIB_SIM
Definition: common_DFE.h:44
int(* calcqgdKernelDFE_dll)(size_t rows, size_t cols, DFEgate_kernel_type *gates, int gatesNum, int gateSetNum, int traceOffset, double *trace)
Definition: common_DFE.cpp:48
Structure type representing complex numbers in the SQUANDER package.
Definition: QGDTypes.h:38
#define DFE_LIB_9QUBITS
Definition: common_DFE.h:42
Class to store data of complex arrays and its properties.
Definition: matrix.h:38
int size() const
Call to get the number of the allocated elements.
int get_initialize_id()
Call to get the identification number of the inititalization of the library.
Definition: common_DFE.cpp:190
Fixed point data related to a gate operation.
Definition: common_DFE.h:61
std::atomic_size_t read_count(0)
reference counting of locking-unlocking the DFE accelerators
void unload_dfe_lib()
Call to unload the DFE libarary and release the allocated devices.
Definition: common_DFE.cpp:78
std::recursive_mutex libmutex
mutex to guard DFE lib locking and unlocking
Definition: common_DFE.cpp:40
#define DFE_LIB_10QUBITS
Definition: common_DFE.h:43
int calcqgdKernelDFE(size_t rows, size_t cols, DFEgate_kernel_type *gates, int gatesNum, int gateSetNum, int traceOffset, double *trace)
Call to execute the calculation on the reserved DFE engines.
Definition: common_DFE.cpp:207
size_t get_accelerator_avail_num()
Call to get the available number of accelerators.
Definition: common_DFE.cpp:169
Header file for DFE support in unitary simulation.
size_t get_accelerator_free_num()
Call to get the number of free accelerators.
Definition: common_DFE.cpp:180
int initialize_id
Definition: common_DFE.cpp:57
size_t(* get_accelerator_free_num_dll)()
Definition: common_DFE.cpp:47
int(* get_chained_gates_num_dll)()
Definition: common_DFE.cpp:52