pyttb icon indicating copy to clipboard operation
pyttb copied to clipboard

ktensor.full() improvements

Open ghbrown opened this issue 8 months ago • 2 comments

The current implementation of .full() for ktensors is extremely memory and compute intensive. It's easy to run out of memory with tensor of modest size but high rank, since the current algorithm requires memory proportional to rank. I believe an einsum based approach would be much more efficient.

Consider the timing results for the code below.

n = 1000:
  full tensor size: ~8 GB
  current .full() profiling: 107 s, 120 GB peak memory usage
  einsum based .full():      65 s,  8 GB peak memory usage

n = 100:  (as evidence that einsum outperforms for small tensors too)
  current .full() profiling: 0.1s
  einsum based .full():      0.06s
import pyttb
import numpy as np
import time

def einfull(w,fm_list):
    return np.einsum('r,ir,jr,kr->ijk',w,*fm_list)

n = 1000
r = 10
w = np.random.rand(r)
A = np.random.rand(n,r)
B = np.random.rand(n,r)
C = np.random.rand(n,r)
K = pyttb.ktensor()
K.weights = w
K.factor_matrices = [A,B,C]
t_0 = time.perf_counter()
T = K.full()
# T = einfull(w,[A,B,C])
t_1 = time.perf_counter()
print(t_1 - t_0)

ghbrown avatar Jun 21 '24 23:06 ghbrown