#ifndef _MSC_VER extern "C" { #include #include #include } #else #include #include #include #include #endif #include #include #include #include #include #include #include #include #ifdef _MSC_VER #include std::string get_cpu_name(); std::string get_cpu_name() { int CPUInfo[4] = { -1 }; __cpuid(CPUInfo, 0x80000000); unsigned int nExIds = CPUInfo[0]; char CPUBrandString[0x40] = { 0 }; for (unsigned int i = 0x80000000; i <= nExIds; ++i){ __cpuid(CPUInfo, i); if (i == 0x80000002) memcpy(CPUBrandString,CPUInfo,sizeof(CPUInfo)); else if (i == 0x80000003) memcpy(CPUBrandString + 16,CPUInfo,sizeof(CPUInfo)); else if (i == 0x80000004) memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo)); } return std::string(CPUBrandString); } #else #include std::string get_cpu_name(); std::string get_cpu_name(){ char CPUBrandString[0x40]; unsigned int CPUInfo[4] = {0,0,0,0}; __cpuid(0x80000000, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); unsigned int nExIds = CPUInfo[0]; memset(CPUBrandString, 0, sizeof(CPUBrandString)); for (unsigned int i = 0x80000000; i <= nExIds; ++i){ __cpuid(i, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]); if (i == 0x80000002) memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo)); else if (i == 0x80000003) memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo)); else if (i == 0x80000004) memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo)); } return std::string(CPUBrandString); } #endif class Timer { private: std::chrono::system_clock::time_point last; long long stock; bool is_stop; public: Timer() { reset(); is_stop = false; } void reset() { stock = 0; last = std::chrono::system_clock::now(); } double elapsed() { if (is_stop) return stock * 1e-6; else { auto duration = std::chrono::system_clock::now() - last; return (stock + std::chrono::duration_cast(duration).count())*1e-6; } } void temporal_stop() { if (!is_stop) { auto duration = std::chrono::system_clock::now() - last; stock += std::chrono::duration_cast(duration).count(); is_stop = true; } } void temporal_resume() { if (is_stop) { last = std::chrono::system_clock::now(); is_stop = false; } } }; double timeout = 0.5; UINT max_repeat = 1000000; UINT firstrun = 1000; double benchmark_memory_allocate(UINT n) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; do { timer.temporal_resume(); state = allocate_quantum_state(dim); timer.temporal_stop(); release_quantum_state(state); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); return timer.elapsed() / repeat; }; double benchmark_memory_release(UINT n) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; do { state = allocate_quantum_state(dim); timer.temporal_resume(); release_quantum_state(state); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); return timer.elapsed() / repeat; }; double benchmark_state_func(UINT n, std::functionfunc) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); do { timer.temporal_resume(); func(state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_state_init(UINT n) { return benchmark_state_func(n, initialize_quantum_state); } double benchmark_state_randomize(UINT n) { return benchmark_state_func(n, initialize_Haar_random_state); } template double benchmark_state_stat_func(UINT n, std::functionfunc) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state); do { timer.temporal_resume(); func(state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_state_norm(UINT n) { return benchmark_state_func(n, state_norm_squared); } double benchmark_gate_single_func(UINT n, UINT target, std::functionfunc) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; CTYPE* state; double elapsed; state = allocate_quantum_state(dim); initialize_Haar_random_state(state,dim); timer.reset(); do { func(target, state, dim); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); elapsed = timer.elapsed(); elapsed /= repeat; release_quantum_state(state); return elapsed; }; double benchmark_gate_double_func(UINT n, UINT target1, UINT target2, std::functionfunc) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state,dim); do { timer.temporal_resume(); func(target1, target2, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_gate_dense_single(UINT n, UINT target) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state, dim); CTYPE matrix[4] = { 1.0, 0.0, 0.0, 1.0 }; do { timer.temporal_resume(); single_qubit_dense_matrix_gate(target, matrix, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_gate_dense_two(UINT n, UINT t1, UINT t2) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state, dim); CTYPE matrix[16]; for (UINT i = 0; i < 4; ++i) matrix[4 * i + i] = 1.; do { timer.temporal_resume(); double_qubit_dense_matrix_gate(t1,t2, matrix, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_gate_dense_two_eigen(UINT n, UINT t1, UINT t2) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state, dim); Eigen::Matrix4cd matrix; for (UINT i = 0; i < 4; ++i) matrix(i,i) = 1.; do { timer.temporal_resume(); double_qubit_dense_matrix_gate_eigen(t1, t2, matrix, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_gate_dense_three(UINT n, UINT t1, UINT t2, UINT t3) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state, dim); CTYPE matrix[64]; UINT target[3] = { t1,t2,t3 }; for (UINT i = 0; i < 8; ++i) matrix[8 * i + i] = 1.; do { timer.temporal_resume(); multi_qubit_dense_matrix_gate(target, 3, matrix, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_gate_diag_single(UINT n, UINT target) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state, dim); CTYPE matrix[2] = { 1.0, 1.0 }; do { timer.temporal_resume(); single_qubit_diagonal_matrix_gate(target, matrix, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_gate_phase_single(UINT n, UINT target) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state, dim); CTYPE phase = 1.0; do { timer.temporal_resume(); single_qubit_phase_gate(target, phase, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_gate_single_control_single_target(UINT n, UINT control, UINT target) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state, dim); CTYPE matrix[4] = { 1.0, 0.0, 0.0, 1.0 }; do { timer.temporal_resume(); single_qubit_control_single_qubit_dense_matrix_gate(control, 0, target, matrix, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; double benchmark_gate_multi_control_single_target(UINT n, UINT c1, UINT c2, UINT target) { UINT repeat = 0; ITYPE dim = (1ULL << n); Timer timer; timer.reset(); timer.temporal_stop(); CTYPE* state; state = allocate_quantum_state(dim); initialize_Haar_random_state(state, dim); CTYPE matrix[4] = { 1.0, 0.0, 0.0, 1.0 }; UINT control[2] = { c1,c2 }; UINT cvalue[2] = { 0,1 }; do { timer.temporal_resume(); multi_qubit_control_single_qubit_dense_matrix_gate(control, cvalue, 2, target, matrix, state, dim); timer.temporal_stop(); repeat++; } while (timer.elapsed() < timeout && repeat <= max_repeat); release_quantum_state(state); return timer.elapsed() / repeat; }; void show(std::string name, UINT qubit_count, double elapsed_time, std::string filename) { std::cout << std::fixed << std::setw(20) << name << std::setw(5) << qubit_count << " " << std::setw(20) << std::setprecision(2) << elapsed_time*1e9 << " ns" << std::endl; std::ofstream fout(filename, std::ios::app); fout << std::fixed << std::setw(20) << name << std::setw(5) << qubit_count << " " << std::setw(20) << std::setprecision(2) << elapsed_time * 1e9 << " ns" << std::endl; fout.close(); //fout << name << " " << qubit_count << " " << elapsed << std::endl; } int main() { const UINT min_qubit_count = 5; const UINT max_qubit_count = 25; const double timeout = 0.1; const UINT max_repeat = 10; const UINT max_dense_qubit_count = 5; #ifdef _MSC_VER std::string compiler_name = "msvc"; #elif __GNUG__ std::string compiler_name = "gcc"; #elif __clang__ std::string compiler_name = "clang"; #else std::string compiler_name = "unknowncompiler"; #endif std::string fname = "bench_" + compiler_name + "_" + get_cpu_name() + ".txt"; std::ofstream fout(fname, std::ios::out); fout.close(); for (UINT qubit_count = min_qubit_count; qubit_count < max_qubit_count; ++qubit_count) { //show("memory allocate", qubit_count, benchmark_memory_allocate(qubit_count), fname); //show("memory release", qubit_count, benchmark_memory_release(qubit_count), fname); //show("state initialize", qubit_count, benchmark_state_init(qubit_count), fname); //show("state randomize", qubit_count, benchmark_state_randomize(qubit_count), fname); //show("gate X_0", qubit_count, benchmark_gate_single_func(qubit_count, 0, X_gate), fname); //show("gate X_1", qubit_count, benchmark_gate_single_func(qubit_count, 1, X_gate), fname); //show("gate X_3", qubit_count, benchmark_gate_single_func(qubit_count, 3, X_gate), fname); //show("gate Y_3", qubit_count, benchmark_gate_single_func(qubit_count, 3, Y_gate), fname); //show("gate Z_3", qubit_count, benchmark_gate_single_func(qubit_count, 3, Z_gate), fname); //show("gate H_3", qubit_count, benchmark_gate_single_func(qubit_count, 3, H_gate), fname); //show("gate P0_3", qubit_count, benchmark_gate_single_func(qubit_count, 3, P0_gate), fname); //show("gate CX_2,3", qubit_count, benchmark_gate_double_func(qubit_count, 2, 3, CNOT_gate), fname); //show("gate CZ_2,3", qubit_count, benchmark_gate_double_func(qubit_count, 2, 3, CZ_gate), fname); //show("gate SWAP_2,3", qubit_count, benchmark_gate_double_func(qubit_count, 2, 3, SWAP_gate), fname); //show("gate diag_3", qubit_count, benchmark_gate_diag_single(qubit_count, 3), fname); //show("gate phase_3", qubit_count, benchmark_gate_phase_single(qubit_count, 3), fname); //show("gate single_3", qubit_count, benchmark_gate_dense_single(qubit_count, 3), fname); //show("gate single_control_single_target_2,3", qubit_count, benchmark_gate_single_control_single_target(qubit_count, 2, 3), fname); //show("gate multi_control_single_target_2,3", qubit_count, benchmark_gate_multi_control_single_target(qubit_count, 1,2, 3), fname); //show("gate two_2,3", qubit_count, benchmark_gate_dense_two(qubit_count, 2,3), fname); show("gate two_eigen_2,3", qubit_count, benchmark_gate_dense_two_eigen(qubit_count, 2, 3), fname); //show("gate three_1,2,3", qubit_count, benchmark_gate_dense_three(qubit_count, 1,2,3), fname); /* for(UINT k=1;k<=max_dense_qubit_count;++k){ ITYPE matrix_dim = 1ULL << k; ComplexMatrix matrix = ComplexMatrix::Identity(matrix_dim,matrix_dim); CTYPE* ptr = (CTYPE*)matrix.data(); UINT* targets = (UINT*)calloc(sizeof(UINT),k); for(UINT m=0;m