Linux에서는 프로세스 실행 시 필요한 메모리를 바로 할당하는 것이 아니라 메모리를 주었다는 것을 저장하는 Memory Commit 정책을 가지고 있다. 실제 메모리 할당은 프로세스가 실행되면서 메모리가 필요할 때 이루어진다.
그리고 Linux는 Overcommit를 허용하는데, 이는 커밋된 메모리가 실제 가용 메모리보다 더 큰 것을 뜻한다. Overcommit 덕분에 메모리 사용량이 큰 프로세스가 있어도 실행될 수가 있다. 그런데 Overcommit이 된 상태에서 프로세스에게 실제 메모리 할당이 되면 가용 메모리보다 더 큰 메모리를 할당할 수도 있는데, 이 때 OOM(Out Of Memory)이 발생하기 때문에 Overcommit은 OOM의 주요 원인으로 손꼽힌다.
OOM Killer과 OOM Score
OOM이 발생하면 메모리 확보를 위해 프로세스를 강제로 종료 시키는 OOM Killer가 실행된다. OOM Killer이 프로세스를 종료할 때 당연히 무작위로 종료하는 것은 아니고, OOM Score에 따라서 종료될 프로세스가 결정된다. OOM Score은 0~1000 사이의 값을 가지고, 값이 클 수록 종료 우선순위가 높아진다. 따라서 OOM Killer는 OOM Score이 높은 순서대로 프로세스를 종료한다.
OOM Score은 oom_badness()를 통해 계산된다. Heuristic하게 계산되는 점수인 만큼 시간이 지나면서 점수 계산 방법이 여러 번 바뀌었던 것 같은데 현재는 기본적으로 메모리 사용량이 높을 수록 OOM Score이 높아진다.
oom_score_adj 값은 OOM Score 조정 값이다. OOM Score를 계산하는 oom_badness()를 보면 마지막에 adj이 OOM Score에 더해지는 것을 볼 수 있다. oom_score_adj 값이 -1000이면 OOM Score LONG_MIN 값을 가져서 종료되지 않는다.
따라서 하나의 머신에서 서버를 포함한 여러 개의 프로세스가 실행되어 있는데, OOM이 발생해도 OOM Killer가 서버 프로세스를 종료하지 않도록 하기 위해서는 서버 프로세스의 oom_score_adj 값을 -1000으로 바꾸면 된다.
모델과 토크나이저에 대해서 push_to_hub()메소드를 이용하여 바로 모델을 업로드하는 방법이 있습니다. 이 방법을 이용하면 원격 저장소 생성까지 한 후에 업로드를 해줍니다.
from transformers import AutoTokenizer, AutoModelForCausalLM
print("model loading...")
# Model & Tokenizer loading
tokenizer = AutoTokenizer.from_pretrained("sshleifer/tiny-gpt2")
model = AutoModelForCausalLM.from_pretrained("sshleifer/tiny-gpt2")
# Repository 생성 & model upload
REPO_NAME = YOUR_REPO_NAME # ex) 'my-bert-fine-tuned'
AUTH_TOKEN = YOUR_OWN_TOKEN # <https://huggingface.co/settings/token>
## Upload to Huggingface Hub
model.push_to_hub(
REPO_NAME,
use_temp_dir=True,
use_auth_token=AUTH_TOKEN
)
tokenizer.push_to_hub(
REPO_NAME,
use_temp_dir=True,
use_auth_token=AUTH_TOKEN
)
위 코드를 통해 모델을 업로드할 때, 권한을 위한 토큰값이 필요합니다.
Huggingface 홈페이지에 로그인한 후 오른쪽 상단 프로필 > Settings > Access Tokens을 누르거나 로그인 후에 링크를 클릭하면 바로 토큰을 관리할 수 있는 페이지가 나타납니다. 페이지 상단을 보면 User Access Tokens부분이 있는데, 여기서 New token을 눌러 토큰을 생성할 수 있습니다. 이 때, Role을 read로 하면 권한 에러가 발생하므로 write로 설정해야합니다.
이렇게 생성된 토큰값을 AUTH_TOKEN의 값으로 이용하면 됩니다.
2. CLI 이용
다음은 CLI환경에서 모델을 업로드하는 방법입니다. 우선 아래 코드를 이용해 모델과 토크나이저가 model 디렉토리에 저장되어 있다고 하겠습니다.
from transformers import AutoTokenizer, AutoModelForCausalLM
print("model loading...")
# Model & Tokenizer loading
tokenizer = AutoTokenizer.from_pretrained("sshleifer/tiny-gpt2")
model = AutoModelForCausalLM.from_pretrained("sshleifer/tiny-gpt2")
tokenizer.save_pretrained("./model")
model.save_pretrained("./model")
이후 이용법은 깃허브에 파일을 올리는 것과 동일합니다.
다만 모델의 용량이 큰 것은 수십GB에 이르기 때문에 용량이 큰 파일도 업로드 할 수 있도록 git lfs(Large File Storage)를 설치합니다. 설치가 완료되면 user.email과 user.name을 huggingface 계정의 이메일과 이름으로 설정해줍니다.
마지막으로 transformers 패키지를 설치하면 같이 설치되는 huggingface-hub 패키지를 이용하는 방법이 있는데, 이를 이용하면 코드 상에서 모델 업로드 뿐만 아니라 더 많은 작업을 수행할 수 있습니다. 주의할 점은 ipynb파일에서만 작업이 가능한 점입니다.
먼저 아래 코드로 huggingface 계정과 연동시킬 수 있는데, 위의 과정과 마찬가지로 토큰값이 필요합니다.
from huggingface_hub import notebook_login
notebook_login()
create_repo()와 delete_repo()를 이용하면 원격 저장소를 생성하고, 삭제할 수 있습니다.
from huggingface_hub import create_repo
# Repository 생성
create_repo(name=REPO_NAME)
# Repository 삭제
delete_repo(name=REPO_NAME
아래 코드를 이용하면 Repository 객체를 생성할 수 있습니다. 여기서 첫 번째 인자는 생성할 로컬 저장소 이름이고, 두 번째 인자는 연동할 원격 저장소 이름입니다. 코드를 실행하면 객체가 생성되면서 원격 저장소의 파일들이 로컬 저장소에 복사되고, 객체를 이용해서 원격 저장소와 관련된 작업들을 할 수 있습니다.
from huggingface_hub import Repository
repo = Repository(LOCAL_DIR_NAME, clone_from=NAMESPACE/REPO_NAME)
그리고 upload_file()를 이용하면 add, commit, push 작업 없이 바로 하나의 파일을 업로드할 수도 있습니다. 여기서는 굳이 로컬 저장소에 있지 않은 파일도 업로드가 가능합니다. path_in_repo 인자값은 원격 저장소에 저장되는 파일의 이름입니다.
from huggingface_hub import upload_file, delete_file
# 파일을 직접 업로드
upload_file(
LOCAL_FILE_PATH,
path_in_repo=REPO_FILE_PATH,
repo_id=NAMESPACE/REPO_NAME,
)
delete_file()를 이용하면 원격 저장소의 파일을 바로 삭제할 수도 있습니다.
# 파일 삭제
delete_file(
REPO_FILE_PATH,
repo_id=NAMESPACE/REPO_NAME,
)