淺析計算GMAC和GFLOPS
GMAC 代表“Giga Multiply-Add Operations per Second”(每秒千兆乘法累加運算),是用于衡量深度學(xué)習(xí)模型計算效率的指標(biāo)。它表示每秒在模型中執(zhí)行的乘法累加運算的數(shù)量,以每秒十億 (giga) 表示。
乘法累加 (MAC) 運算是許多數(shù)學(xué)計算中的基本運算,包括矩陣乘法、卷積和深度學(xué)習(xí)中常用的其他張量運算。每個 MAC 操作都涉及將兩個數(shù)字相乘并將結(jié)果添加到累加器。
可以使用以下公式計算 GMAC 指標(biāo):
GMAC =(乘法累加運算次數(shù))/(10?)
乘加運算的數(shù)量通常通過分析網(wǎng)絡(luò)架構(gòu)和模型參數(shù)的維度來確定,例如權(quán)重和偏差。
通過 GMAC 指標(biāo),研究人員和從業(yè)者可以就模型選擇、硬件要求和優(yōu)化策略做出明智的決策,以實現(xiàn)高效且有效的深度學(xué)習(xí)計算。
GFLOPS 代表“每秒千兆浮點運算”,是用于衡量計算機系統(tǒng)或特定運算的計算性能的指標(biāo)。它表示每秒執(zhí)行的浮點運算次數(shù),也是以每秒十億 (giga) 表示。
浮點運算包括涉及以 IEEE 754 浮點格式表示的實數(shù)的算術(shù)計算。這些運算通常包括加法、減法、乘法、除法和其他數(shù)學(xué)運算。
GFLOPS 通常用于高性能計算 (HPC) 和基準測試,特別是在需要繁重計算任務(wù)的領(lǐng)域,例如科學(xué)模擬、數(shù)據(jù)分析和深度學(xué)習(xí)。
計算 GFLOPS公式如下:
GFLOPS =(浮點運算次數(shù))/(以秒為單位的運行時間)/ (10?)
GFLOPS 是比較不同計算機系統(tǒng)、處理器或特定操作的計算性能的有用指標(biāo)。它有助于評估執(zhí)行浮點計算的硬件或算法的速度和效率。GFLOPS 是衡量理論峰值性能的指標(biāo),可能無法反映實際場景中實現(xiàn)的實際性能,因為它沒有考慮內(nèi)存訪問、并行化和其他系統(tǒng)限制等因素。
GMAC 和 GFLOPS 之間的關(guān)系
1 GFLOP = 2 GMAC
如果我們想計算這兩個指標(biāo),手動寫代碼的話會比較麻煩,但是Python已經(jīng)有現(xiàn)成的庫讓我們使用:
ptflops 庫就可以計算 GMAC 和 GFLOPs
pip install ptflops
使用也非常簡單:
import torchvision.models as models
import torch
from ptflops import get_model_complexity_info
import re
#Model thats already available
net = models.densenet161()
macs, params = get_model_complexity_info(net, (3, 224, 224), as_strings=True,
print_per_layer_stat=True, verbose=True)
# Extract the numerical value
flops = eval(re.findall(r'([\d.]+)', macs)[0])*2
# Extract the unit
flops_unit = re.findall(r'([A-Za-z]+)', macs)[0][0]
print('Computational complexity: {:<8}'.format(macs))
print('Computational complexity: {} {}Flops'.format(flops, flops_unit))
print('Number of parameters: {:<8}'.format(params))
結(jié)果如下:
Computational complexity: 7.82 GMac
Computational complexity: 15.64 GFlops
Number of parameters: 28.68 M
我們可以自定義一個模型來看看結(jié)果是否正確:
import os
import torch
from torch import nn
class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10),
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
custom_net = NeuralNetwork()
macs, params = get_model_complexity_info(custom_net, (28, 28), as_strings=True,
print_per_layer_stat=True, verbose=True)
# Extract the numerical value
flops = eval(re.findall(r'([\d.]+)', macs)[0])*2
# Extract the unit
flops_unit = re.findall(r'([A-Za-z]+)', macs)[0][0]
print('Computational complexity: {:<8}'.format(macs))
print('Computational complexity: {} {}Flops'.format(flops, flops_unit))
print('Number of parameters: {:<8}'.format(params))
結(jié)果如下:
Computational complexity: 670.73 KMac
Computational complexity: 1341.46 KFlops
Number of parameters: 669.71 k
我們來嘗試手動計算下GMAC,為了演示方便我們只寫全連接層的代碼,因為比較簡單。計算GMAC的關(guān)鍵是遍歷模型的權(quán)重參數(shù),并根據(jù)權(quán)重參數(shù)的形狀計算乘法和加法操作的數(shù)量。對于全連接層的權(quán)重,GMAC的計算公式為 (輸入維度 x 輸出維度) x 2。根據(jù)模型的結(jié)構(gòu),將每個線性層的權(quán)重參數(shù)形狀相乘并累加得到總的GMAC值。
import torch
import torch.nn as nn
def compute_gmac(model):
gmac_count = 0
for param in model.parameters():
shape = param.shape
if len(shape) == 2: # 全連接層的權(quán)重
gmac_count += shape[0] * shape[1] * 2
gmac_count = gmac_count / 1e9 # 轉(zhuǎn)換為十億為單位
return gmac_count
根據(jù)上面給定的模型,計算GMAC的結(jié)果如下:
0.66972288
GMAC的結(jié)果是以十億為單位,所以跟我們上面用類庫計算的結(jié)果相差不大。最后再說一下,計算卷積的GMAC稍微有些復(fù)雜,公式為 ((輸入通道 x 卷積核高度 x 卷積核寬度) x 輸出通道) x 2,這里給一個簡單的代碼,不一定完全正確,供參考
def compute_gmac(model):
gmac_count = 0
for param in model.parameters():
shape = param.shape
if len(shape) == 2: # 全連接層的權(quán)重
gmac_count += shape[0] * shape[1] * 2
elif len(shape) == 4: # 卷積層的權(quán)重
gmac_count += shape[0] * shape[1] * shape[2] * shape[3] * 2
gmac_count = gmac_count / 1e9 # 轉(zhuǎn)換為十億為單位
return gmac_count