2025-plovdiv-comp-arch/exercise-my-solution.ipynb
2025-08-13 13:58:07 +02:00

6.4 KiB

In [1]:
import numpy as np
In [2]:
n_series = 32
len_one_series = 5*2**20
time_series = np.random.rand(n_series, len_one_series)
gap = 16*2**10
In [3]:
print(f'Size of one time series: {int(time_series[0].nbytes/2**20)} M')
print(f'Size of collection: {int(time_series.nbytes/2**20)} M')
print(f'Gap size: {int(gap*8/2**10)} K')
print(f'Gapped series size: {int(time_series[0, ::gap].nbytes/2**10)} K')
Size of one time series: 40 M
Size of collection: 1280 M
Gap size: 128 K
Gapped series size: 2 K

The following function implements an approximation of a power series of every gap value in our time series.

If we define one time series of length N to be:

$[x_0, x_1, x_2, ..., x_N]$,

then the "gapped" series with gap=g is:

$[x_0, x_g, x_{2g}, ..., x_{N/g}]$,

where $N/g$ is the number of gaps.

The approximation of the power series up to power 30 for our "gapped" series is defined as:

$$\mathbf{P} = \sum_{p=0}^{30} \sum_i x_i^{p} = \sum_i x_i^0 + \sum_i x_i^1 + \sum_i x_i^2 + ... + \sum_i x_i^{30} $$

where $i \in [0, g, 2g, ..., N/g]$

In [4]:
# compute an approximation of a power series for a collection of gapped timeseries
def power(time_series, P, gap):
    for row in range(time_series.shape[0]):
        for pwr in range(30):
            P[row] += (time_series[row, ::gap]**pwr).sum()
    return P

Challenge

  • Can you improve on the above implementation of the power function?
  • Change the following power_improved function and see what you can do
  • Remember: you can't change any other cell in this notebook!
In [5]:
def power_improved(time_series, P, gap):
    y = time_series[:,::gap].copy()
    for row in range(time_series.shape[0]):
        for pwr in range(30):
            P[row] += (y[row, :]**pwr).sum()
    return P
In [6]:
# verify that they yield the same results
P = np.zeros(n_series, dtype='float64')
out1 = power(time_series, P, gap)
P = np.zeros(n_series, dtype='float64')
out2 = power_improved(time_series, P, gap)
np.testing.assert_allclose(out1, out2)
In [7]:
P = np.zeros(n_series, dtype='float64')
%timeit power(time_series, P, gap)
38.9 ms ± 492 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [8]:
P = np.zeros(n_series, dtype='float64')
%timeit power_improved(time_series, P, gap)
6.79 ms ± 35.2 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [ ]: