Если у вас есть несколько графических процессоров, вы можете распределить вычисления по всем из них, используя PyTorch DataParallel
.Он разделит (распараллелит) умножение столбцов матрицы C_gpu
между графическими процессорами.
Вот как:
Сначала импортируйте модули и подготовьте матрицы:
import torch
import torch.nn as nn
A_gpu = torch.from_numpy(A).float()
B_gpu = torch.from_numpy(B).float()
C_gpu = torch.from_numpy(C).float()
Далее создайте Linear
«слой» без смещения.То, что делает этот слой - это именно матричное умножение.Размер ввода будет равен размеру каждого столбца C_gpu
, а размер вывода равен размеру каждого столбца результата.
mat_mult = nn.Linear(in_features=C_gpu.shape[0],out_features=A_gpu.shape[0],bias=False)
Установите для матрицы (= вес) слоя значениеbe A_gpu @ B_gpu
, которая представляет собой небольшую матрицу, которая может быть быстро вычислена без распараллеливания (хотя вы также можете распараллелить ее, если хотите).
mat_mult.weight.data = A_gpu @ B_gpu
Преобразовать слой в экземпляр DataParallel.Это означает, что он будет автоматически распараллеливать вычисления по «пакетному» измерению.Аргумент device_ids
представляет собой список индексов ваших графических процессоров (4 из них, в вашем случае).
mat_mult_gpu = nn.DataParallel(mat_mult,device_ids=[0,1,2,3]).to('cuda:0')
Теперь вы можете вставить матрицу C_gpu
в слой, и вычисление будетпараллельно его большому размеру:
D_gpu = mat_mult_gpu(C_gpu.t())
ВАЖНОЕ ПРИМЕЧАНИЕ: При написании этого ответа у меня не было доступа к нескольким графическим процессорам, чтобы фактически протестировать это предлагаемое решение.Я буду признателен, если кто-нибудь из читателей подтвердит, что он действительно работает (и даже лучше - оцените время и сравните с одним GPU)
EDIT1: Я сейчас попробовал этокод на нескольких графических процессорах (четыре Nvidia Tesla P100), и оказывается, что выдает ошибку нехватки памяти.Я оставлю это решение здесь для справки, поскольку оно подходит для размеров до 400 КБ (вместо 3,6 МБ).
Кроме того, это решение будет работать и для размеров 3,6M, если вы разделите C
на более мелкие куски, подадите каждый кусок в mat_mult_gpu
, а затем объедините результаты в ЦП.Обратите внимание, что вам нужно много памяти процессора для этого, так как результат имеет размер 3K-by-3.6M
, который в fp32 занимает около 40 ГБ.(в качестве альтернативы вы можете сохранить каждый чанк на диск без объединения чанков).