Efficient autograd for sparse matrices multiplication

Viewed 106

I have two pretty big sparse matrices (3M x 200k, with 60M nonzero entries). Their values are parameters that I would like to learn. The loss function is defined based on the product of these two matrices - for simplicity let's assume it's just a sum of entries.

I tried PyTorch, but it seems backward() is very slow (I'm not advanced in PyTorch so maybe I made some mistake). Here is the code (with much smaller matrices):

from time import time
import torch
import numpy as np

def test_sparse_speed(a1, a2, b2, density_A, density_B):
    b1 = a2
    nnz_A = int(density_A * a1 * a2)
    nnz_B = int(density_B * b1 * b2)
    
    print(f'Matrix A shape: [{a1}, {a2}], nonzero entries: {nnz_A}')
    print(f'Matrix B shape: [{b1}, {b2}], nonzero entries: {nnz_B}\n')
    
    # create first matrix
    indexA = np.array([np.random.randint(0, a1, (nnz_A, )), np.random.randint(0, a2, (nnz_A, ))])
    valueA = torch.ones(nnz_A, requires_grad=True)
    A = torch.sparse_coo_tensor(
        indexA,
        valueA,
        size=[a1, a2],
    )

    # create second matrix
    indexB = np.array([np.random.randint(0, b1, (nnz_B, )), np.random.randint(0, b2, (nnz_B, ))])
    valueB = torch.ones(nnz_B, requires_grad=True)
    B = torch.sparse_coo_tensor(
        indexB,
        valueB,
        size=[b1, b2],
    )
    
    start = time()
    y = torch.sparse.mm(A, B)
    print(f'Multiplication time: {time()-start} seconds')
    
    loss = y.coalesce().values().sum()
    
    start = time()
    loss.backward()
    print(f'Backward time: {time()-start} seconds')
    return A, B

A, B = test_sparse_speed(a1=100, a2=10**5, b2=10**4, density_A=0.005, density_B=0.0002)

--->

Matrix A shape: [100, 100000], nonzero entries: 50000
Matrix B shape: [100000, 10000], nonzero entries: 200000

Multiplication time: 0.03313016891479492 seconds
Backward time: 28.99043607711792 seconds

How to do it more efficiently? I'm open to trying another library.

0 Answers
Related