quantum/load_test.py

127 lines
6.8 KiB
Python

from sys import getsizeof
from time import time
import numpy as np
import pyximport
from lib_q_computer import Qubit, __0, kron
pyximport.install()
def sizeof_fmt(num, suffix='B'):
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Yi', suffix)
def run_load_test(N=20):
"""
Runs a load test with max N qubits (up to and including N).
Expectation is that on a 8GB laptop I should be able to run about 30 qubits using 8-byte numbers.
(2**30 * 8 ) / 1024**3 = 8.0
Example run output with N=27 on 64GB machine **(without jit, without cython optimizations)**
qbits kron_len mem_used mem_per_q getsizeof getsiz/len nbytes nbytes/len time
2 4 0.0B 0.0B 144.0B 36.0B 32.0B 8.0B 0.0
3 8 0.0B 0.0B 176.0B 22.0B 64.0B 8.0B 0.0
4 16 0.0B 0.0B 240.0B 15.0B 128.0B 8.0B 0.0
5 32 0.0B 0.0B 368.0B 11.5B 256.0B 8.0B 0.0
6 64 0.0B 0.0B 624.0B 9.8B 512.0B 8.0B 0.0
7 128 0.0B 0.0B 1.1KiB 8.9B 1.0KiB 8.0B 0.0
8 256 0.0B 0.0B 2.1KiB 8.4B 2.0KiB 8.0B 0.0
9 512 312.0KiB 624.0B 4.1KiB 8.2B 4.0KiB 8.0B 0.0
10 1024 312.0KiB 312.0B 8.1KiB 8.1B 8.0KiB 8.0B 0.0
11 2048 312.0KiB 156.0B 16.1KiB 8.1B 16.0KiB 8.0B 0.0
12 4096 816.0KiB 204.0B 32.1KiB 8.0B 32.0KiB 8.0B 0.0
13 8192 1.2MiB 150.5B 64.1KiB 8.0B 64.0KiB 8.0B 0.01
14 16384 1.9MiB 123.5B 128.1KiB 8.0B 128.0KiB 8.0B 0.01
15 32768 3.4MiB 110.1B 256.1KiB 8.0B 256.0KiB 8.0B 0.02
16 65536 6.5MiB 103.3B 512.1KiB 8.0B 512.0KiB 8.0B 0.04
17 131072 11.5MiB 91.9B 1.0MiB 8.0B 1.0MiB 8.0B 0.08
18 262144 22.6MiB 90.2B 2.0MiB 8.0B 2.0MiB 8.0B 0.18
19 524288 44.7MiB 89.4B 4.0MiB 8.0B 4.0MiB 8.0B 0.32
20 1048576 88.9MiB 88.9B 8.0MiB 8.0B 8.0MiB 8.0B 0.66
21 2097152 177.5MiB 88.7B 16.0MiB 8.0B 16.0MiB 8.0B 1.31
22 4194304 354.5MiB 88.6B 32.0MiB 8.0B 32.0MiB 8.0B 2.67
23 8388608 676.6MiB 84.6B 64.0MiB 8.0B 64.0MiB 8.0B 5.26
24 16777216 1.3GiB 84.5B 128.0MiB 8.0B 128.0MiB 8.0B 10.59
25 33554432 2.6GiB 84.5B 256.0MiB 8.0B 256.0MiB 8.0B 21.3
26 67108864 5.3GiB 84.5B 512.0MiB 8.0B 512.0MiB 8.0B 41.81
27 134217728 10.6GiB 84.5B 1.0GiB 8.0B 1.0GiB 8.0B 83.76
TODO: Understand numby.jit magic (look at the results differences > 20qbits, mem usage /10; time /4)
...
20 1048576 39.7MiB 39.7B 112.0B 0.0B 8.0MiB 8.0B 0.16
21 2097152 51.7MiB 25.9B 112.0B 0.0B 16.0MiB 8.0B 0.33
22 4194304 75.7MiB 18.9B 112.0B 0.0B 32.0MiB 8.0B 0.63
23 8388608 123.7MiB 15.5B 112.0B 0.0B 64.0MiB 8.0B 1.26
24 16777216 187.7MiB 11.7B 112.0B 0.0B 128.0MiB 8.0B 2.51
25 33554432 315.7MiB 9.9B 112.0B 0.0B 256.0MiB 8.0B 5.05
26 67108864 571.7MiB 8.9B 112.0B 0.0B 512.0MiB 8.0B 10.05
27 134217728 1.1GiB 8.5B 112.0B 0.0B 1.0GiB 8.0B 19.86
28 268435456 2.1GiB 8.2B 112.0B 0.0B 2.0GiB 8.0B 40.79
29 536870912 4.1GiB 8.1B 112.0B 0.0B 4.0GiB 8.0B 81.07
30 1073741824 8.1GiB 8.1B 112.0B 0.0B 8.0GiB 8.0B 161.68
...
Also together with cython optimization (time /4) (but right now it seems to take only doubles):
...
20 1048576 23.7MiB 23.7B 8.0MiB 8.0B 8.0MiB 8.0B 0.04
21 2097152 35.7MiB 17.8B 16.0MiB 8.0B 16.0MiB 8.0B 0.08
22 4194304 59.7MiB 14.9B 32.0MiB 8.0B 32.0MiB 8.0B 0.15
23 8388608 107.7MiB 13.5B 64.0MiB 8.0B 64.0MiB 8.0B 0.3
24 16777216 171.7MiB 10.7B 128.0MiB 8.0B 128.0MiB 8.0B 0.59
25 33554432 299.7MiB 9.4B 256.0MiB 8.0B 256.0MiB 8.0B 1.18
26 67108864 555.7MiB 8.7B 512.0MiB 8.0B 512.0MiB 8.0B 2.35
27 134217728 1.0GiB 8.3B 1.0GiB 8.0B 1.0GiB 8.0B 4.7
28 268435456 2.0GiB 8.2B 2.0GiB 8.0B 2.0GiB 8.0B 9.52
29 536870912 4.0GiB 8.1B 4.0GiB 8.0B 4.0GiB 8.0B 19.32
30 1073741824 8.0GiB 8.0B 8.0GiB 8.0B 8.0GiB 8.0B 37.76
"""
_0 = Qubit(__0)
import os
import psutil
import gc
print("{:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>10}".format(
"qbits",
"kron_len",
"mem_used",
"mem_per_q",
"getsizeof",
"getsiz/len",
"nbytes",
"nbytes/len",
"time"))
process = psutil.Process(os.getpid())
mem_init = process.memory_info().rss
for i in range(2, N + 1):
start = time()
qbits = [_0.matrix_state for _ in range(i)]
m = kron(qbits)
len_m = len(m)
elapsed = time() - start
mem_b = process.memory_info().rss - mem_init
print("{:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>10}".format(
i,
len(m),
sizeof_fmt(mem_b),
sizeof_fmt(mem_b / len_m),
sizeof_fmt(getsizeof(m)),
sizeof_fmt(getsizeof(m) / len_m),
sizeof_fmt(m.nbytes),
sizeof_fmt(m.nbytes / len_m),
np.round(elapsed, 2)))
gc.collect()
if __name__ == "__main__":
run_load_test(30)