24
24
from tensorflow_quantum .core .ops import tfq_simulate_ops_cuda
25
25
from tensorflow_quantum .python import util
26
26
27
+ def measure_average_runtime (fn , tag , num_samples = 10 ):
28
+ avg_time = []
29
+ for _ in range (num_samples ):
30
+ begin_time = time .time ()
31
+ result = fn ()
32
+ duration = time .time () - begin_time
33
+ avg_time .append (duration )
34
+ avg_time = sum (avg_time ) / float (num_samples )
35
+ print (f"\n \t { tag } time: { avg_time } \n " )
36
+ return avg_time , result
37
+
27
38
28
39
class SimulateExpectationTest (tf .test .TestCase ):
29
40
"""Tests tfq_simulate_expectation."""
30
41
31
- def test_simulate_expectation_diff (self ):
32
- """Make sure that cpu & gpu ops have the same results."""
33
- # TF 2
34
- # gpus = tf.config.list_physical_devices('GPU')
35
- # self.assertLess(len(gpus), 1)
36
- # if len(gpus) < 1:
37
- # self.skipTest("Expected at least 1 GPU but found {} GPUs".format(
38
- # len(gpus)))
42
+ def test_simulate_expectation_cpu_vs_cuda (self ):
43
+ """Make sure that cpu & gpu(cuda) ops have the same results."""
39
44
n_qubits = 20
40
45
batch_size = 5
41
46
symbol_names = ['alpha' ]
@@ -54,77 +59,27 @@ def test_simulate_expectation_diff(self):
54
59
pauli_sums = util .random_pauli_sums (qubits , 3 , batch_size )
55
60
pauli_sums_tensor = util .convert_to_tensor ([[x ] for x in pauli_sums ])
56
61
57
- cpu_avg_time = []
58
- for _ in range (10 ):
59
- cpu_time = time .time ()
60
- res_cpu = tfq_simulate_ops .tfq_simulate_expectation (
62
+ cpu_avg_time , res_cpu = measure_average_runtime (
63
+ lambda : tfq_simulate_ops .tfq_simulate_expectation (
61
64
circuit_batch_tensor ,
62
65
symbol_names , symbol_values_array .astype (np .float64 ),
63
- pauli_sums_tensor )
64
- cpu_time = time .time () - cpu_time
65
- cpu_avg_time .append (cpu_time )
66
- cpu_avg_time = sum (cpu_avg_time ) / 10.0
67
- print ("\n \t CPU time: " , cpu_avg_time , "\n " )
68
-
69
- avg_cpu_with_gpu_time = []
70
- for _ in range (10 ):
71
- cpu_with_gpu_time = time .time ()
72
- with tf .device ("/device:GPU:0" ):
73
- res_cpu_with_gpu = tfq_simulate_ops_cuda .tfq_simulate_expectation (
74
- circuit_batch_tensor ,
75
- symbol_names , symbol_values_array .astype (np .float64 ),
76
- pauli_sums_tensor )
77
- cpu_with_gpu_time = time .time () - cpu_with_gpu_time
78
- avg_cpu_with_gpu_time .append (cpu_with_gpu_time )
79
- avg_cpu_with_gpu_time = sum (avg_cpu_with_gpu_time ) / 10.0
80
-
81
- # Both are CPU devices.
82
- self .assertEqual (res_cpu .device , res_cpu_with_gpu .device )
83
- np .testing .assert_allclose (res_cpu , res_cpu_with_gpu )
84
- print ("\n \t CPU with GPU device time: " , avg_cpu_with_gpu_time , "\n " )
85
-
86
- @tf .function
87
- def cpu_with_gpu_fn ():
88
- with tf .device ("/device:GPU:0" ):
89
- return tfq_simulate_ops_cuda .tfq_simulate_expectation (
90
- circuit_batch_tensor ,
91
- symbol_names , symbol_values_array .astype (np .float64 ),
92
- pauli_sums_tensor )
66
+ pauli_sums_tensor ),
67
+ "CPU"
68
+ )
93
69
94
- avg_fn_cpu_with_gpu_time = []
95
- for _ in range (10 ):
96
- fn_cpu_with_gpu_time = time .time ()
97
- res_fn_cpu_with_gpu = cpu_with_gpu_fn ()
98
- fn_cpu_with_gpu_time = time .time () - fn_cpu_with_gpu_time
99
- avg_fn_cpu_with_gpu_time .append (fn_cpu_with_gpu_time )
100
- avg_fn_cpu_with_gpu_time = sum (avg_fn_cpu_with_gpu_time ) / 10.0
101
-
102
- # CPU & GPU devices.
103
- self .assertNotEqual (res_cpu .device , res_fn_cpu_with_gpu .device )
104
- np .testing .assert_allclose (res_cpu , res_fn_cpu_with_gpu )
105
- print ("\n \t tf.function, CPU with GPU device time: " ,
106
- avg_fn_cpu_with_gpu_time , "\n " )
107
-
108
- # avg_gpu_time = []
109
- # for _ in range(10):
110
- # gpu_time = time.time()
111
- # res_gpu = tfq_simulate_ops_gpu_cpu.tfq_simulate_expectation(
112
- # circuit_batch_tensor,
113
- # symbol_names, symbol_values_array.astype(np.float64),
114
- # pauli_sums_tensor)
115
- # gpu_time = time.time() - gpu_time
116
- # avg_gpu_time.append(gpu_time)
117
- # avg_gpu_time = sum(avg_gpu_time) / 10.0
118
- # print("\n\tGPU version time: ", avg_gpu_time, "\n")
70
+ cuda_avg_time , res_cuda = measure_average_runtime (
71
+ lambda : tfq_simulate_ops_cuda .tfq_simulate_expectation (
72
+ circuit_batch_tensor ,
73
+ symbol_names , symbol_values_array .astype (np .float64 ),
74
+ pauli_sums_tensor ),
75
+ "CUDA"
76
+ )
119
77
78
+ # The result should be the similar within a tolerance.
79
+ np .testing .assert_allclose (res_cpu , res_cuda , atol = 1e-5 )
120
80
121
- # # This guarantees that both tensors are not in the same devices
122
- # # (e.g. CPU vs GPU)
123
- # # self.assertNotEqual(res.device, res_gpu.device)
124
- # # -> this doesn't work anymore because TFQ op itself is in CPU.
125
- # # only qsim::SimulatorCUDA is in GPU
126
- # np.testing.assert_allclose(res_cpu, res_gpu)
127
- # self.assertGreater(cpu_avg_time, avg_gpu_time)
81
+ # CUDA op should be faster than CPU op.
82
+ self .assertGreater (cpu_avg_time , cuda_avg_time )
128
83
129
84
130
85
if __name__ == "__main__" :
0 commit comments