在 Windows 及 Linux 分別安裝如下套件
#Windows pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu1330 --no-cache-dir #Linux pip install torch torchvision torchaudio
batch
每次 batch 不要超過 1e8(1億),否則 12 G 的 VRAM 也不夠用。
使用 CPU
底下程式在主記憶体(RAM, 非顯卡記憶体)配置 x, y 變數,然後使用 CPU 計算 batch = 1 億,每個 epoch 約需 0.9 秒多。若是使用 numpy,每個 epoch 約需 2 秒。
import time
import torch
def count():
x=torch.rand(batch)
y=torch.rand(batch)
d=torch.sqrt(torch.square(x)+torch.square(y))
idx=torch.where(d<=1)
return idx[0].shape[0]
batch=1_00_000_000
epochs=200
incircle=0
for e in range(epochs):
t1=time.time()
incircle+=count()
t2=time.time()
print(f"{t2-t1:.5f}秒")
pi=4*incircle/((e+1)*batch)
print(f"epoch:{e+1}: pi={pi}")
結果:
1.12293秒
epoch:1: pi=3.1415254
1.03121秒
epoch:2: pi=3.14150678
0.95390秒
epoch:3: pi=3.141532773333333
0.96214秒
epoch:4: pi=3.14151597
使用 GPU
底下程式在每個 epoch 都重新配置一次新的顯卡記憶体(VRAM),然後使用 GPU 計算 batch = 1 億,每個 epoch 約需 0.007 秒多。
import time
import torch
def count():
x=torch.rand(batch , device="cuda:0")
y=torch.rand(batch , device="cuda:0")
d=torch.sqrt(torch.square(x)+torch.square(y))
idx=torch.where(d<=1)
return idx[0].shape[0]
batch=1_000_000_000
epochs=200
incircle=0
for e in range(epochs):
t1=time.time()
incircle+=count()
t2=time.time()
print(f"{t2-t1:.5f}秒")
pi=4*incircle/((e+1)*batch)
print(f"epoch:{e+1}: pi={pi}")
結果:
0.19113秒
epoch:1: pi=3.14157944
0.02380秒
epoch:2: pi=3.14165164
0.00750秒
epoch:3: pi=3.14167188
0.00695秒
epoch:4: pi=3.14171002
0.00850秒
epoch:5: pi=3.141717616
優化 GPU
底下在主程式只配置一次顯卡的記憶体(VRAM),每個 epoch 不再重新配置新記憶体,只修改原配置RAM 內 的值,效能高,這稱為 in-place 操作。計算 batch = 1 億雖也是 0.007 秒多,但若在大資料量時,會節省很多時間。
import time import torch def count(): x.uniform_(0, 1) y.uniform_(0, 1) return (x*x+y*y<=1).sum().item() device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") batch=1_000_000_000 epochs=200 incircle=0 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") x=torch.zeros(batch).to(device) y=torch.zeros(batch, device=device) for e in range(epochs): t1=time.time() incircle+=count() t2=time.time() print(f"{t2-t1:.5f}秒") pi=4*incircle/((e+1)*batch) print(f"epoch:{e+1}: pi={pi}") 結果 : 0.07825秒 epoch:1: pi=3.1417826 0.02338秒 epoch:2: pi=3.14165502 0.00794秒 epoch:3: pi=3.1416211466666666 0.00856秒 epoch:4: pi=3.14172572 0.00764秒 epoch:5: pi=3.141665792
(x*x+y*y<=1) 會產生 [True, True, False, True, …….],sum 會把裏面的值加總,但會先將 True 轉成 1,False 轉成 0,所以加總後是計算幾個 True,然後用 item() 將 tensor 轉成 Python 數字。
