benchmark.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import click
  2. import time
  3. import random
  4. import statistics
  5. import csv
  6. import os.path
  7. import math
  8. from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit
  9. from qiskit.wrapper import load_qasm_file
  10. from qiskit import QISKitError, execute, Aer
  11. from projectq import MainEngine
  12. import projectq.ops as ops
  13. from projectq.backends import Simulator
  14. import qcgpu
  15. # Implementation of the Quantum Fourier Transform
  16. def construct_circuit(num_qubits):
  17. q = QuantumRegister(num_qubits)
  18. circ = QuantumCircuit(q)
  19. # Quantum Fourier Transform
  20. for j in range(num_qubits):
  21. for k in range(j):
  22. circ.cu1(math.pi/float(2**(j-k)), q[j], q[k])
  23. circ.h(q[j])
  24. return circ
  25. # Benchmarking functions
  26. qiskit_backend = Aer.get_backend('statevector_simulator')
  27. eng = MainEngine(backend=Simulator(), engine_list=[])
  28. # Setup the OpenCL Device
  29. qcgpu.backend.create_context()
  30. def bench_qiskit(qc):
  31. start = time.time()
  32. job_sim = execute(qc, qiskit_backend)
  33. sim_result = job_sim.result()
  34. return time.time() - start
  35. def bench_qcgpu(num_qubits):
  36. start = time.time()
  37. state = qcgpu.State(num_qubits)
  38. for j in range(num_qubits):
  39. for k in range(j):
  40. state.cu1(j, k, math.pi/float(2**(j-k)))
  41. state.h(j)
  42. state.backend.queue.finish()
  43. return time.time() - start
  44. def bench_projectq(num_qubits):
  45. start = time.time()
  46. q = eng.allocate_qureg(num_qubits)
  47. for j in range(num_qubits):
  48. for k in range(j):
  49. ops.CRz(math.pi / float(2**(j-k))) | (q[j], q[k])
  50. ops.H | q[j]
  51. eng.flush()
  52. t = time.time() - start
  53. # measure to get rid of runtime error message
  54. for j in q:
  55. ops.Measure | j
  56. return t
  57. # Reporting
  58. def create_csv(filename):
  59. file_exists = os.path.isfile(filename)
  60. csvfile = open(filename, 'a')
  61. headers = ['name', 'num_qubits', 'time']
  62. writer = csv.DictWriter(csvfile, delimiter=',', lineterminator='\n',fieldnames=headers)
  63. if not file_exists:
  64. writer.writeheader() # file doesn't exist yet, write a header
  65. return writer
  66. def write_csv(writer, data):
  67. writer.writerow(data)
  68. @click.command()
  69. @click.option('--samples', default=5, help='Number of samples to take for each qubit.')
  70. @click.option('--qubits', default=5, help='How many qubits you want to test for')
  71. @click.option('--out', default='benchmark_data.csv', help='Where to store the CSV output of each test')
  72. @click.option('--single', default=False, help='Only run the benchmark for a single amount of qubits, and print an analysis')
  73. def benchmark(samples, qubits, out, single):
  74. if single:
  75. # functions = bench_qcgpu, bench_qiskit, bench_projectq
  76. functions = bench_projectq,
  77. times = {f.__name__: [] for f in functions}
  78. names = []
  79. means = []
  80. qc = construct_circuit(qubits)
  81. # Run the benchmarks
  82. for i in range(samples):
  83. progress = (i) / (samples)
  84. if samples > 1:
  85. print("\rProgress: [{0:50s}] {1:.1f}%".format('#' * int(progress * 50), progress*100), end="", flush=True)
  86. func = random.choice(functions)
  87. if func.__name__ != 'bench_qiskit':
  88. t = func(qubits)
  89. else:
  90. t = func(qc)
  91. times[func.__name__].append(t)
  92. print('')
  93. for name, numbers in times.items():
  94. print('FUNCTION:', name, 'Used', len(numbers), 'times')
  95. print('\tMEDIAN', statistics.median(numbers))
  96. print('\tMEAN ', statistics.mean(numbers))
  97. if len(numbers) > 1:
  98. print('\tSTDEV ', statistics.stdev(numbers))
  99. return
  100. functions = bench_qcgpu, bench_qiskit, bench_projectq
  101. # times = {f.__name__: [] for f in functions}
  102. writer = create_csv(out)
  103. for n in range(23, qubits):
  104. # Progress counter
  105. progress = (n+1) / (qubits)
  106. print("\rProgress: [{0:50s}] {1:.1f}%".format('#' * int(progress * 50), progress*100), end="", flush=True)
  107. # Construct the circuit
  108. qc = construct_circuit(n+1)
  109. # Run the benchmarks
  110. for i in range(samples):
  111. func = random.choice(functions)
  112. if func.__name__ != 'bench_qiskit':
  113. t = func(n + 1)
  114. else:
  115. t = func(qc)
  116. # times[func.__name__].append(t)
  117. write_csv(writer, {'name': func.__name__, 'num_qubits': n+1, 'time': t})
  118. if __name__ == '__main__':
  119. benchmark()