연구실에 서버가 여러대가 있다.
각 서버의 GPU 사용량을 스프레드시트에 자동으로 업데이트 하면 좋을 것 같아 만들어 봤다.
대략 이런 느낌으로 업데이트 되도록 했다.
누군가 관심이 생긴다면 보고 따라해보면 좋을 듯 하다.
전체적인 과정은 다음과 같다.
1. 각 서버에서 일정 시간마다 코드를 실행시킨다.
2. 실행된 코드는 스프레드 시트 api로 웹 request를 보낸다.
3. request를 받으면 자동으로 입력되도록 한다.
코드에 사용된 언어는 python이며, 각자 잘 하는 언어를 사용해도 무방하다.
자 그러면 우선 서버에서 실행되는 코드부터 보도록 하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
import os
from re import template
import requests
import argparse
parser = argparse.ArgumentParser(description='PyTorch GPU USAGE')
parser.add_argument('--n', default=0, type=int,
metavar='N', help='gpu num')
result_str = os.popen('nvidia-smi | grep MiB').read()
lines = result_str.split('\n')
usage_list = []
max_list = []
temperature_list = []
user_list = []
for line in lines:
tmp = line.split('|')
if len(tmp) == 5:
usage = tmp[2].replace(' ', '')
temperature_list.append(tmp[1].split()[1])
usage_list.append(usage.split('/')[0])
max_list.append(usage.split('/')[1])
if len(tmp) == 3:
foruser = tmp[1].split()
if int(foruser[6].split('MiB')[0]) > 100:
result_user = os.popen(f'ps -u -p {foruser[3]}').read()
user_list.append(result_user.split('\n')[1].split()[0])
gpu_num = len(usage_list)
user_num = len(user_list)
params = {}
params['gpu_num'] = gpu_num
params['user_num'] = user_num
for i in range(gpu_num):
params[f'usage{i}'] = usage_list[i]
params[f'max{i}'] = max_list[i]
params[f"temperature{i}"] = temperature_list[i]
for i in range(user_num):
params[f'user{i}'] = user_list[i]
args = parser.parse_args()
params["line"] = args.n
URL = "https://script.google.com/macros/s/YOURSCRIPTID/exec"
res = requests.post(URL, data=params)
|
cs |
어려울건 없다.
os.popen은 cmd 명령어를 실행해주고 read()를 통해 그 결과를 받아와 준다.
스프레드 시트에 입력하고 싶은 것들은 총 3가지다.
1. GPU 온도
2. GPU 현재용량 / 최대용량
3. 코드를 사용하고 있는 사용자.
1, 2번은 nvidia-smi를 통해 얻을 수 있으며
3번은 100MiB 이상 사용하고 있는 프로그램의 PID를 얻어 해당 PID가 어떤 계정에서 돌고있는 프로그램인지 얻어냈다.
이후 params를 통해 POST를 하여 넘겨준다.
이 때 배열은 안넘어가길래 궁여지책으로 딕셔너리의 키값에 번호를 붙여 넘겼다...
좋은 방법이 있을 텐데 나는 초보라 잘 모르겠다.
그 다음엔 스프레드 시트에서 해당 데이터를 받아오는 부분이다.
스프레드 시트를 하나 연 뒤, 도구->스크립트 편집기를 클릭한다.
필자는 이런 코드를 사용했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
function doGet(e){
return ContentService.createTextOutput("test").setMimeType(ContentService.MimeType.TEXT);
}
function doPost(e){
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/YOURSHEETURL/edit");
// var sheet = ss.getSheetByName('GPU'); // be very careful ... it is the sheet name .. so it should match
var activesheet = ss.getActiveSheet();
var line = e.parameter["line"]*3 + 4
for (var i=0; i<e.parameter["gpu_num"]; i++){
var tmp = "usage" + i
var maximum = "max"+i
var temperature = "temperature"+i
activesheet.getRange(line, 6+i).setValue(e.parameter[tmp]+"/"+e.parameter[maximum] +" ("+e.parameter[temperature]+")");
}
for (var i=0; i<10; i++){
if (i<e.parameter["user_num"]){
var tmp = "user" + i
activesheet.getRange(line, 11+i).setValue(e.parameter[tmp]);
}
else{
activesheet.getRange(line, 11+i).setValue("");
}
}
return ContentService.createTextOutput("Success").setMimeType(ContentService.MimeType.TEXT);
}
|
cs |
중요한 함수는 doPost 이다.
인자로 받아온 e.parameter에 python코드에서 넘긴 데이터가 들어가있다.
하나씩 빼서 원하는 곳에 넣어준다.
참고로 getRange(줄, 열) 이라 생각하면 된다.
이 스크립트 코드를 배포를 해줘야 한다. 배포를 하면 웹앱 주소가 나올텐데 해당 주소를 파이썬 코드에 붙여넣고 실행시켜보자.
이렇게 쓴 결과
잘 출력된다.
참고로 밑의 막대바는 GPU사용정도를 표현한 것이고, 다음과 같이 만들었다.
=SPARKLINE(((LEFT(SUBSTITUTE(Left(G16, Find("(",G16)-2),"MiB",""), FIND("/",SUBSTITUTE(Left(G16, Find("(",G16)-2),"MiB",""))-1)*100/MID(SUBSTITUTE(Left(G16, Find("(",G16)-2),"MiB",""), FIND("/",SUBSTITUTE(Left(G16, Find("(",G16)-2),"MiB",""))+1, 100))),{"charttype","bar"; "max", 100})
해석은.. 알아서 하길 바란다.
자 이제 주기적으로 서버에서 python 코드를 실행시켜줘야 한다.
간단하다.
서버에 다음 코드를 입력한다.
crontab -e
그리고 밑의 코드를 입력한다.
5/N * * * * /usr/bin/python3.8 /GPU_usage.py --n 5
5/N은 5분마다 한번씩 실행하겠다는 이야기이다. 자세한 것은 crontab 사용법을 찾아보길 바란다.
중요한 점은 python 3.7 이상 버전의 절대경로를 넣어줘야 한다는 것이다.
(필자의 경우 3.8의 절대경로를 넣어줬다.)
그리고 그 뒤에 만들어둔 python 코드를 넣어준다.
인자로 --n 을 통해 숫자를 넘겨주는데, 이 숫자는 몇번째 서버인지를 나타낸다.
스프레드 시트에 해당 숫자만큼 밑으로 이동해 채워넣어주고 있다. (파이썬 코드와 script 코드를 참고하자)
이후 sudo service cron start 을 실행시켜 활성화를 시켜준다.
(이러면 서버가 꺼졌다 켜져도 계속 실행된다)
뭘 하려 했든 이 전체적인 흐름과 코드들이 도움이 되길 바란다.
나는 연구실 서버 여러대에 모두 코드를 넣어두고 실행시켜놨다. 매 5분마다 한번씩 업데이트 된다.