Sidenote: Optimizing our code
What will this section cover?
- Optimizing the Pearson Correlation Coefficient calculations
As you may have noticed our algorithm is now really slow. This is due to the calculation of Pearson Correlation Coefficients. We can speed this up by a lot if we notice a couple of things.
- \(\sqrt{a}\sqrt{b}=\sqrt{a b}\). Since square rooting is a very expensive operation, we can optimize the calculation of \(\sigma_x \sigma_y\) from two square root calculations to one.
- We are recalculating a lot of averages and standard deviations. We can pre-compute these averages and standard deviations and fetch them instead of recomputing them.
- Since we only care about the maximum correlation coefficient and have no interest in the value itself, we can stop doing any factorization.
In the following code we have created a function which applies these three optimized functions when calculating the correlation coefficients.
point_means = np.mean(traces, axis=0, dtype=np.float64)
point_mean_diff = traces - point_means
point_mean_diff_squared_sum = np.sum(np.power(point_mean_diff, 2), axis=0)
def optimized_calculate_correlation_coefficients(subkey, subkey_index):
# Declare a numpy for the hypothetical power usage
hypothetical_power = np.zeros(num_traces)
for trace_index in range(0, num_traces):
hypothetical_power[trace_index] = hypothetical_power_usage(
subkey,
textins[trace_index][subkey_index]
)
hypothetical_power_mean = np.mean(hypothetical_power, dtype=np.float64)
hypothetical_power_mean_diff = hypothetical_power - hypothetical_power_mean
hypothetical_power_mean_diff_sum_squared = np.sum(
np.power(hypothetical_power_mean_diff, 2)
)
# We are going to the determine correlations between each trace point
# and the hypothetical power usage. This will save all those coefficients
point_correlation = np.zeros(num_points)
# Loop through all points and determine their correlation coefficients
for point_index in range(0, num_points):
point_correlation[point_index] = np.sum(
hypothetical_power_mean_diff *
# Look at the individual traces points for every trace
point_mean_diff[:, point_index]
) / np.sqrt(hypothetical_power_mean_diff_sum_squared *
point_mean_diff_squared_sum[point_index])
return point_correlation
After optimizing the calculations of the Pearson correlation
coefficients, our crack.py
script should run a lot
faster.