建構一個大型AI系統,常常會在許多地方呼叫模型,但是模型佔用資源龐大,不可以無限制的實例。
當然可以透過傳遞的方式將模型傳給各別模組,但是可能會變成一個傳遞地獄;或是透過約定一個全域變數的方式來達成,這方法可行但仍然不夠好。
這時候就輪到單例模式登場了,單例模式只允許同個類別存在一個實例,若多次執行類別實例動作,則返回已經實例化的類別。沒有傳遞與管理全域變數的問題!
下面的範例使用一個裝飾器(decorator)來達到單例目的,而從輸出可以發現我們成功避免多次實例同個類別。
from transformers import AutoTokenizer, AutoModelForMaskedLM
from time import time
def singleton(class_):
instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
class BigModel():
def __init__(self):
self.tokenizer = AutoTokenizer.from_pretrained("albert-base-v2")
# instance a big model
self.model = AutoModelForMaskedLM.from_pretrained("albert-base-v2")
@singleton
class SingletonBigModel(BigModel):
"""
當類別存在則返回已經實例過後的類別
"""
pass
if __name__ == "__main__":
for i in range(3):
start_time = time()
model = BigModel()
print(f"i: {i}, {id(model)}, {round(time() - start_time,5)}/s")
for j in range(3):
start_time = time()
model = SingletonBigModel()
print(f"j: {j}, {id(model)}, {round(time() - start_time,5)}/s")
i: 0, 4694351680, 10.1407/s
i: 1, 4728420672, 10.21932/s
i: 2, 4694351680, 10.03433/s
j: 0, 4310527856, 11.0801/s
j: 1, 4310527856, 0.0/s
j: 2, 4310527856, 0.0/s