마찬가지로 풀다가 살짝 막히거나(시간이 조금 걸렸거나), 기본 라이브러리를 다시 짚게 된 경우만을 기록.

또는 내가 생각치 못한 다른 방법?이 있는 경우에도 기록.


Level 0 - 피자 나눠 먹기 (1)

"""
7조각으로 잘라줌
모든사람이 한조각 이상 먹기
필요한 피자 판의 갯수

=> n 나누기 7 => 2.xx => 올림 => 3판
=> 나눠진 값을 올림하기
"""
import math

def solution(n):
    answer = math.ceil(n / 7)
    return answer
  • 항상 반올림만을 쓰는 round를 사용했었기에, 올림은 뭐였지..? 하다가 검색.
  • 내장 module math를 사용해서 올림 연산.
  • 모든사람이 한 조각 이상을 먹어야 하므로 $\rightarrow$ 인수(n)를 7로 나누고, 이를 올림해주기.

 

 

 

Level 0 - 삼각형의 완성조건 (1)

"""
가장 긴 변의 길이는 다른 두 변의 길이의 합보다 작다

만들 수 있으면 1, 만들 수 없으면 2
"""
def solution(sides):
    # sides를 sort 하고
    sides.sort()

    # 맨 끝의 원소(가장 긴 변)가 다른 두 원소의 합보다 크면 1, 아니면 2
    # 배열의 길이는 3으로 고정 -> 배열 전체를 훑을 필요가 X
    if sides[2] < sides[0] + sides[1]:
        answer = 1
    else:
        answer = 2

    return answer
  • 가장 긴 변은 정렬할 경우 가장 끝에 위치하므로 우선 정렬.
  • 현재 list의 길이가 3으로 고정되어 있으므로, list 전체를 훑을 필요가 없음.
    • 나머지 2개의 합보다 큰지, 작은지만 판단.

쉬운데.. 적은 이유는 풀고 나서 다른사람의 풀이를 보았기 때문.

def solution(sides):
    return 1 if max(sides) < (sum(sides) - max(sides)) else 2

PS쟁이들이 언제나 간결하게 적는거야 그렇다 치는데... 이 max 라는 걸 완전히 잊었었기 때문.
C/C++이나 java에서 sort가 없었나? 해서 옛날이라면 나도 이런식으로 풀었을텐데... Python에 내장된 함수가 너무 간편하다 보니 다짜고짜 정렬부터 생각해버린 듯.

 

 

 

Level 0 - 점의 위치 구하기

처음 풀이...

def solution(dot):
    # dot은 [n1, n2] 로 구성된 list
    # 단순히 점 1개1개가 어디에 있는지를 판단?
    
    answer = 0
    # 1사분면 & 3사분면 => dot[0]이 양수 
    if dot[0] > 0:
        # 1사분면
        if dot[1] > 0:
            answer = 1
        # 3사분면
        else:
            answer = 4
    # 2사분면 & 4사분면 => dot[0]이 음수
    elif dot[0] > 0:
        # 2사분면
        if dot[1] > 0:
            answer = 2
        # 4사분면
        else:
            answer = 4        
        
    return answer

이렇게 풀었는데 에러가 나와서 보니, 0이 아님이 있어서 다시 수정.

def solution(dot):
    # dot은 [n1, n2] 로 구성된 list
    # 단순히 점 1개1개가 어디에 있는지를 판단?
    # 문제 조건에 0이 아님이 있음
    
    answer = 0
    # 1사분면 & 4사분면 => dot[0]이 양수 
    if dot[0] > 0 and dot[0] != 0:
        # 1사분면
        if dot[1] > 0 and dot[1] != 0:
            answer = 1
        # 3사분면
        elif dot[1] < 0 and dot[1] != 0:
            answer = 4
    # 2사분면 & 4사분면 => dot[0]이 음수
    elif dot[0] > 0 and dot[0] != 0:
        # 2사분면
        if dot[1] > 0 and dot[1] != 0:
            answer = 2
        # 4사분면
        elif dot[1] < 0 and dot[1] != 0:
            answer = 4        
        
    return answer

했는데 또 오답이 있다.

 

결국 신입생 시절 C/C++ 로 일일히 분기했던 기억을 되삼아 그냥 단순무식하게 작성.

def solution(dot):
    # dot은 [n1, n2] 로 구성된 list
    # 단순히 점 1개1개가 어디에 있는지를 판단?
    # 문제 조건에 0이 아님이 있음
    
    answer = 0
    # 1사분면 => dot[0]이 양수, dot[1]이 양수
    if dot[0] > 0 and dot[1] > 0:
        answer = 1
    
    # 2사분면 => dot[0]이 음수, dot[1]이 양수
    elif dot[0] < 0 and dot[1] > 0:
        answer = 2

    # 3사분면 => dot[0]이 음수, dot[1]이 음수
    if dot[0] < 0 and dot[1] < 0:
        answer = 3
    
    # 4사분면 => dot[0]이 양수, dot[1]이 음수
    elif dot[0] > 0 and dot[1] < 0:
        answer = 4
        
    return answer

 

단순한 문제인데... 너무 단순하게 생각해서 그런지 첫번째, 두번째 작성했던 걸 보니 예외가 걸리긴 한다.

다른사람들은 어떻게 풀었을까.. 하고 보니

def solution(dot):
    x,y = dot
    if x*y>0:
        return 1 if x>0 else 3
    else:
        return 4 if x>0 else 2

 

Python에서 list 2개의 값을 그냥 저렇게 꺼내올 수 있다는 게 다시 기억났다.

(기억상 석사과정 당시 간간히 썼었던 것 같긴 하다)

+ 이렇게 하면 두 좌표값의 곱으로 양수/음수로 판단하고, 이에따라 몇사분면인지 판단을 할 수 있는 것.

 

언제나 배워간다.

 

 

 

Level 0 - 순서쌍의 개수

def solution(n):
    # 순서쌍 -> 약수 pair를 구하기
    answer = 0
    number_list = []
    
    # 주어진 수 까지 loop를 돌며 약수를 구하기
    for i in range(1, n+1):
        if (n % i) == 0:
            number_list.append(i)
    
    # pair는 2개씩 묶이므로 -> len(list) 자체가 pair의 개수
    answer = len(number_list)
    return answer

 

  • 약수를 구하는 마땅한 함수?가 없는 걸로 기억.
  • 주어진 수 까지 1부터 시작해서 loop를 돌리고, 주어진 수 n이 현재의 수 i와 나눠지는지 확인, 나눠진다면 이 i는 n의 약수이므로 append.

다른사람들의 풀이를 보니... 굳이 list를 선언 할 필요가 없기는 했다.

def solution(n):
    answer = 0
    for i in range(1, int(n ** 0.5) + 1):
        if n % i == 0:
            answer += 2

            if i * i == n:
                answer -= 1

    return answer

 

이런 방법도 있더라.

나눠지는 경우와 더불어, 제곱인 경우를 빼주는 case...

'학업 이야기 > Algorithm & PS' 카테고리의 다른 글

[Programmers] Level 0 이모저모 (1)  (0) 2026.01.14

하반기가 끝나고, 프로그래머스에서 일하고 있는 친구의 조언을 받아 Level 0부터 문제를 풀기 시작.

확실히 친구 조언대로 수치심을 버리고 Level 0부터 차근차근 풀어가는게 맞는듯..

 

뇌가 너무 딱딱해져있는 상태라... 생각하는데 시간이 조금이라도 걸렸던 문제들을 기록으로 남기고자 한다.

(쉽게 풀린건 따로 기록 X)

 


 

Level 0 - 양꼬치

"""
양꼬치 1인분 12000
음료수 2000
10인분 먹으면 음료수 1개 공짜
"""
def solution(n, k):
    # # 10인분 먹으면 1개 공짜 
    # if n % 10 == 0:
    #     k = k-(n//10)
    #     print(k)
    answer = 12000 * n + 2000 * (k - (n//10))
    return answer

 

  • 10인분이 1개 공짜 이므로
  • 공짜로 주는 음료수 개수가 n//10 개가 되고
  • 금액 계산할때 k에서 이를 빼주기

 

 

 

Level 0 - 짝수의 합

def solution(n):
    evens = []
    
    # n이하 정수를 생성하고
    # 짝수만 저장
    for numbers in range(n+1):
        if numbers % 2 == 0:
            evens.append(numbers)
    
    # sum
    answer = sum(evens)
    return answer

 

  • n이하의 짝수가 필요하므로, for~range를 통해 정수 loop
  • 짝수인 경우 (%2 == 0)엔 evens에 추가하면
  • evens엔 (0을 포함한) 짝수만 담겨져있으므로
  • sum()을 통해 전체 합 계산

 

 

 

Level 0 - 배열 뒤집기

def solution(num_list):
    # answer = num_list.sort(reverse=True)
    # answer = sorted(num_list, reverse=True) # 3번 case: [5,3,1,1,1,1,0] <=> [5,3,1,1,1,0,1]
    
    # 역순 indexing?
    # answer = num_list[-1:]
    
    # 하나씩 pop 해서 새로운 list에 담기?
    answer = []
    for i in range(len(num_list)):
        answer.append(num_list.pop())

    return answer
  • sort를 하니, 같은 숫자가 같이 묶이는 문제.
  • list를 역순으로 indexing... 하면 될 거 같은데, python을 기초부터 배운게 아닌지라 감이 안잡혀서 다르게 생각.
  • 하나씩 pop 해서 새로은 list에 담기
num_list[::-1]​

 

num_list.reverse()
  • 풀고 나서 다른 사람의 풀이 를 보니, 생각한 기능이 역시나...

 

 

 

Level 0 - 뒤집힌 문자열

def solution(my_string):
    # string을 list로 변환
    string_list = list(my_string)
    
    # list reverse
    string_list.reverse()
    
    # 원소를 하나씩 결합해서 뒤집힌 문자열 생성
    for string in string_list:
        answer += string
        
    return answer
  • 앞 문제에서 익혔던 reverse() 사용
  • 원소를 하나씩 answer에 결합
my_string[::-1]
answer = ''.join(my_list)
  • 확실히 기본부터 배우질 않았어서, string도 list처럼 indexing이 되는 줄 몰랐다.
  • 21년도엔가 백준을 풀면서 많이 사용했던 ''.join() 도 다시 되새겨본다.

 

 

 

 

'학업 이야기 > Algorithm & PS' 카테고리의 다른 글

[Programmers] Level 0 이모저모 (2)  (0) 2026.01.27

어느덧 벌써 25년 한해가 지나간다.

 

작년과는 다르게 뭔가 한달한달 시간이 상당히 빠르게 지나간 듯 한 느낌이 많이 든다.

 

24년때와는 다르게, 25년 자체는 뭔가 크나큰 추억?거리가 엄청 많았던 것 같지는 않은데...

그래도 뒤돌아보면 나름(?) 알차게 보냈나 싶기도 한 해였던 것 같다.

 

작년처럼 촬영했던 사진들을 돌아보며 기억에 남을만한 사건/이벤트 들을 하나씩 되짚어보며 기록을 남겨보고자 한다.

 

 

1월

  • 뭔가 특별한 일이 없었던 것 같다.
  • 어머니 음력 생신과 나의 양력 생일이 며칠 차이가 나지 않았기에, 가족들이 모여서 고양동? 쪽에 있는 무슨 족발/보쌈 집에서 가족 모임을 했었다. 같이 나왔던 김치가 상당히 신기했던 기억.
  • 올해도 친구들이 생일선물로 이런저런 선물을 보내줬었다.
    • 집에서 하도 술을 많이 먹어 그런지, 이번에는 레몬즙을 5개나 보내줬었다 ㅋㅋㅋ...

하나하나 다 비우고, 글을 작성하고 있는 현재도 2개인가가 남아있다 ㅋㅋ

  • 대한항공 정비사로 일하는 대학교 친구가 호출해서, 오랫만에 둘이서 술한잔을 했다.
  • 설날 기념으로 고등학교 친구들과 신촌에서 만나 화로상회에서 회식(?)을 하고, 큰형과 함께 집근처 술집에서 둘이서 술을 먹었다. 아무래도 큰형이랑 단둘이서 먹어본 적이 처음이 아닌가.. 싶긴 하다.
  • 사진첩을 둘러보니 절반 이상이 음주하고 있는 컴퓨터 책상 사진이다 ㅋㅋㅋ;; 참 많이도 마신 듯...

 

  • 게임적으로는 뭔가 적당히 즐긴 듯 하다. 윗판을 올린다기 보다는, 아래쪽에서 노래들을 들으면서 밑판다지기를 많이 했는 듯.
    • 팝픈뮤직의 만우절 어퍼 채보를 노트 한두개 차이로 S를 못했는데... 아직도 이 점수를 못넘기고 있다 :(
      (https://youtu.be/cnmaH8Hsy7I)
    • SDVX에서 처음으로 17레벨 PERFECT를 받았다. 여느때처럼 별 생각 없이 좋아하는 노래를 골랐는데... 얻어 걸려줘서 정말 깜짝 놀랐었다.

지금 다시봐도 참 의아하긴 하다.

  • 동아리 선배와 친구의 조언(?)으로, 너정도면 슬슬 투덱 개전을 따볼만 하지 않냐고 해서 도전...했다가 스크래치에서 빨간약을 너무 심하게 먹어서 현타가 좀 많이 왔었다.
    • 게임을 한지 10년정도 되기는 했는데, 어느새부턴가 단위를 그냥 신경쓰지 않고 살다가 바람잡힌 김에 한번 해봤다가 빨간약을 너무 먹었는 듯 ㅋㅋ... 골고루 플레이하지 않고 스크래치 곡들은 거의 건들지를 않았었으니...

스크래치 곡을 아무리 안하긴 했어도... 다시봐도 참 처참하긴 하다 ㅋㅋㅋ;;

 

 

 

2월

  • 작년(24년)에 같이 졸업했던 후배가 아마 10월? 즈음 부터 잠수를 탔었는데, 연락이 다시 되어서 부모님이 후배를 데리고 넷이서 같이 인제로 겨울 캠핑을 한번 가보가고 하셨다.
    • 인제 필례온천 캠핑장에 가서 의도치않게 혹한기 숙영도 하고, 고기도 구워먹고, 온천도 하고... 여러모로 강력한 추억으로 남은 느낌.

캠핑장 가는길에 들렀던 중국집. 역시 가는길에 들어가는 집이 참 맛있다. 간짜장이 너무 맛있었던 기억이 난다.
텐트를 설치하고 한장.
저녁으로 먹은 바베큐
자고 일어나니 핸드폰도 꺼져있고, 텐트 안에 넣어뒀던 물도 얼어있고, 텐트를 나와보니 흰 서리가 쌓여있었다 ㅋㅋㅋㅋ

  • 이후로는 또 먹고, 마시고, 놀고... 동아리 후배들이랑 같이 오락실에서 놀고 술집에서 3~4시간동안 마시기도 했다.

 

  • 게임적..으로는 뭔가 특별한게 없었던 것 같은 느낌.
    • 아무래도 개전에 한번 도전했다가 마음이 꺾였어서 그런지, 좋아하는 노래들을 들으면서 밑판 다지기를 열심히 한 듯.
    • 팝픈뮤직에서 YAKYU ROCK이 정말 안타까웠던 기억은 확실히 남긴 한다 ㅋㅋㅋ.. 다시봐도 어떻게 저런 점수를 냈는지 참 의아한 듯.
      (https://youtu.be/0DbdDXteiWI)
    • SDVX에서 오랫만에 III 시절 정말 클리어가 힘들었던 Everlasting Message를 했는데, 점수가 생각보다 많이 올라서 놀랐었다.

그래도 거진 8~9년이 지나서 그런지, 확정적으로 클리어는 되긴 하는 듯.

 

 

 

3월

  • 큰형 가족과 함께 신북온천으로 짤막한 여행(?)을 다녀왔다.
    • 이번에는 신북온천 바로 옆에 붙어있던 허름한 모텔이 아닌, 다른곳의 펜션을 빌려서 숙박.
    • 온천을 하고 나와서 저녁을 먹고, 예전처럼 인근 시장에서 닭강정을 포장해서 큰형과 음주.
    • 돌아오는 길에는 포천 이동갈비를 먹고, 마장저수지를 들러 근처 카페에서 커피 한잔.
  • 손목 문제로 계속 쉬고있는 동반입대했던 고등학교 친구와 함께 응암동 찜질방 방문.
    • 둘이서 오랫만에 땀도 쫙 빼고, 근처에 사는 직장인 친구를 불러서 같이 밥 한끼.
  • 사회에서 알게된 친구 모임의 한명이 결혼을 하게 되어 결혼식에 참가
    • 미국에 가있는 친구인지라, (기억상) 미국에서 먼저 결혼식을 올리고, 한국에서는 약간 가족/친척/친구 일부만 불러서 조촐한 파티..?행사..? 를 했었다.
    • 전국 각지에서 친구들이 모두 모였던 만큼, 겸사겸사 친구들끼리 모여서 강남의 파티룸을 빌려 밤새도록 먹고 마시고 놀았다.

처음으로 가본 삼청각. 코스로 나오는 요리라 그런지 하나하나가 전부 맛있었던 기억이 난다.
행사가 끝나고 방문한 강남의 파티룸. 포켓볼도 치고, 게임도 하고, 테이블에 앉아서 보드게임도 하고...

 

  • 게임적으로도 뭔가 대단하다! 했던 특출난 기억은 없는 듯. 팝픈 뮤직을 참 열심히 한 것 같다.
    • 노래가 정말 흥겹고 재밌어서 자주 플레이하는 CHINA ROCK을 AAA 달성해서 참 기뻤던 기억이 난다.
      (https://youtu.be/enri2nfXNKU)
    • 한동안 건들지 않았던 47~48들을 많이 건들고 있었는데, 처음으로 47에서 풀콤보를 달성했었다.
      (https://youtu.be/jgVusZihHws)
    • 정말 오랫만에 49 짠게이지 노래를 하나 클리어해서 정말 기뻤었다.
      (https://youtu.be/z9be7K8ScW4)

 

 

 

4월

  • 학부생때부터 자주 다녔던 & 랩실때부터 자주 다니는 오락실의 지인들과 함께 지인 분의 집에서 음주.
    • 누군가의 집에 모여서 술을 먹는게 너무 오랫만이어서 그랬는지, 이날 어떻게 잠이 들었는지 기억이 나질 않았다 ㅋㅋ...
  • 부모님과 함께 고대산 자연휴양림에 방문.
    • 겸사겸사 고대산을 한번 등산했는데.... 직원분이 악산이라고 한 이유가 있었다.
    • 산 높이 자체는 그렇게 안높았던 것 같은데, 올라가는 길 자체가 상당히 험난했었다.
    • 휴양림에서 하루를 보내고, 돌아오는길에 연천 재인폭포를 들러서 간단한 관광.

오랫만에 등산을 하니 참 상쾌하긴 했는데... 다시 생각해봐도 올라가는 길이 너무 험난했었다.

  • 큰형네 둘째 조카가 첫돌이 되어, 애니골 쪽의 우설화 라는 가게에서 온가족이 모여서 식사.

먹었던 고기가 정말 맛있었던 기억이 난다. 역시 고기류는 비싼 값어치를 하는 듯.

 

  • 상반기 시즌이 시작되고, 잠시 정신없었던 기억도 난다.
    • 중소/중견 기업 지원서도 당시에 처음 작성했었는데, 지원했던 모든 곳이 서류에서 탈락되어 좀 자신감이 많이 떨어졌던 기억이 난다.
    • 그나마 운 좋게(?) KT 서류가 통과되어서, 또다시 인적성 공부를 하고 시험을 봤다.
      시험 자체는 SK보다는 쉽고, CJ랑 엇비슷한 느낌이었는데, 마지막 도형 추리? 였는지 패턴 찾기가 조금 난해했는 듯.
      연습문제 풀 당시에는 막힘없이 그래도 잘 풀리긴 했었는데, 실전을 보니 연습문제랑 도형/패턴들의 생김새? 가 많이 달랐나 그래서 5분정도 뇌정지가 왔었다.
      시험을 보고 나서 아.. 이건 글렀다 했는데 역시는 역시나... ㅠ

자소서 문항들의 글자수가 참 빡빡해서 투덜대며 작성했었는데, 이게 통과되어서 많이 의아했던 기억이 난다.

 

  • 게임적으로는 어느때처럼 천천히 계단올라가기를 한 것 같다.
    • IIDX에서 해금했던 천사의 칸타타를 클리어 해보았다. 그래도 나름 고레벨 악곡을 오랫만에 클리어해서 조금은 기뻤었는 듯.
    • 팝픈쪽에선 본격적으로 47 순회를 돌았던 것 같다. AAA도 이것저것 챙기고(https://youtu.be/unF5XtDpdTU)(https://youtu.be/8idi-G0oAYw)(https://youtu.be/bIsOUJEi8Ks), 의도치 않은 47 두번째 풀콤보(https://youtu.be/J83ffv1ZoIs)도 보고...
    • 본격적으로 순회를 돌면서 밑판을 다져서 그런지, 49가 잘 쳐지기 시작했었다.
      새로운 클리어를 노려서 팝픈 클래스 98.00을 달성하고자 했는데, 결국 클리어가 되지 않아 기록 갱신으로 어찌저찌 98.00을 달성해서 정말 기뻤던 기억이 난다.
      무엇보다 50을 하나도 안건드리고 달성한게 뭔가 참 감회가 새로웠는 듯.
      (https://youtu.be/oeMdD2KqyPo)

노래 자체는 참 ANTHEM 답기는 한데... 계단?폭타?가 참 어렵긴 하다.
팝픈 클래스 98 달성 :)
50을 하나도 안건드리고 달성해서 그런지, 뭔가 오랫만에 느껴보는 성취감이었다.

 

 

 

5월

  • 부모님과 큰형&첫째조카와 함께 영월 망경대산 휴양림에 방문.
    • 가는길에 치악산 쌀 막걸리 주조공장? 같은게 있어서 저렴하게 탁주를 구매. 국도 여행은 지나가면서 이런 숨겨진 요소를 하나씩 찾아가는 재미가 좋은 듯 하다.
    • 돌아오는 길에 한반도 지형에 들러서 사진/영상으로만 보던 지형도 직접 보고, 뗏목도 한번 타봤다.

망경대산 휴양림에서 찍은 사진. 날씨가 너무 좋아서 그런지 풍경이 정말 이뻤다.

 

  • 일본에서 일하고 있는 대학교 동아리 친구가 골든위크를 맞아, 여느때처럼 한국에 방문.
    • 홍대에 에어비앤비 숙소를 잡고, 겸사겸사 동아리 OB 모임을 가졌다.

버튜퍼를 좋아하는 선배가 들고온 노엘 포션(진). 봄베이랑 큰 차이가 없는 느낌이었다.
다음날 해장 겸 방문한 니시무라멘 라멘집. 색다른 느낌이라 맛있긴 했는데, 전날 너무 과음을 해버려서 많이 먹지를 못했다 ㅠ

  • 그리고 여느때와 같은 음주생활 :)
    • 사진첩을 돌아보니, 이때즈음 부터 유튜브에서 자주 봤던 샤와르마(shawarma) 라는 요리?에 많이 꽂혔던 것 같다.
    • 동네 슈퍼에서 또띠아를 사서 직접 만들어 먹어보고, 트레이더스에서 포켓브레드를 사서 만들어 먹어보고...

친구가 선물로 보내줬던 보리소주. 술에서 보리향이 나는게 뭔가 참 색달랐다.
나름(?) 유튜브 영상에서 봤던 기억대로 만들어 본 샤와르마. 대충 입맛대로 소스를 바르고, 야채/채소를 넣고, 고기를 넣고... 이색적인 느낌이 들어서 만들어 먹는 재미가 쏠쏠한 것 같다.

 

  • 대학교 동아리에서, 난생 처음으로 단체 주문제작 티셔츠를 만든다 하여 하나를 구매.

뭔가 참... ㅋㅋㅋㅋㅋ 10년이 지나니 동아리도 꽤 커지면서 별걸 다 하는구나 싶었다.

 

  • 오랫만에 연구실 후배로부터 함께 술 한잔 하자는 연락이 왔다.
    • 당시에 교환 프로그램을 갔다가 (내가 졸업한 후에) 돌아와서 랩실을 그만둔 석박통합 후배도 함께 보자고 했다가, 
      오랫만에 만나는 김에 이친구 저친구도 같이 보자 했더니 어느샌가 랩실 생활때 같이 있었던 후배들 모두를 만나게 되었다.
    • 고속터미널 인근에 모여서 오랫만에 얼굴들을 보니 정말 좋았고, 다들 박사과정도 하고 직장생활도 하는 모습을 보니 좋았다. 다들 참 열심히 살아가는구나... 를 느꼈는 듯.
    • 술 먹으면서 미국에서 박사과정을 밟고있는 동기와도 오랫만에 화상통화로 서로 안부를 물어보고... 참 반가웠다.

저녁을 먹고 2차를 지나 3차로 방문한 술집. 너무 오랫만에들 만나서 좋았는데, 술까지 같이 들어가니 밑도 끝도 없이 먹었던 것 같다. 결국 첫차타고 귀가하긴 했지만, 그래도 오랫만에들 보니 다들 잘 지내고 있는 것 같아 기분이 좋았다.

 

  • 게임적으로는 조금씩 트라우마도 극복하고, 계단을 한층 더 올라간 듯 하다.
    • 자주 다니는 오락실에서 IIDX에 타건음 마이크를 설치해 준 덕분에, 입문시절 목표곡 중 하나인 Blue Rain 黑 채보를 영상으로 남길 수 있어서 정말 좋았다 :)
      (https://youtu.be/Ak-XzaJwBDs)
    • A~A+ 라인의 노래들을 조금씩 하드클리어 했는 듯. 예전에 비해 그래도 처리력이 오르긴 올랐구나 를 느꼈다.
      (https://youtu.be/uLFbrEfNYAM) (https://youtu.be/Qz3N2vFoSlg)
    • 팝픈뮤직 쪽에서도 47~48에서 밑판 다지기를 열심히 해서 그런지, 전체적으로 스코어링들이 잘 되었던 것 같다.

 

 

 

6월

  • 3~4월까지 한번씩 일용직으로 갔던 쿠팡 물류센터가 계속해서 반려당해서, 알바자리를 찾다가 운 좋게 집 바로 앞의 편의점 오후 알바를 하게 되었다. (본격적인 시작은 5월 말이긴 했지만...)
    • 그래도 랩실 다닐때 만큼의 한달 인건비 정도는 벌려서, 어느정도 안심되는 기분이긴 했다.
  • 부모님과 큰형수&조카들과 함께 철원의 두루웰 숲속문화촌? 이라는 곳을 방문.
    • 가는 길에 마장호수 출렁다리도 둘러보고, 예전에 한번 갔었던 고석정도 다시 한번 가보고...
    • 돌아오는 길엔 한탄강 주상절리도 둘러보았다. 비가 내려서 물이 많이 탁했지만, 경치 자체는 참 좋았는 듯.

숙소 구조가 뭔가 참 신기하게 생겼었다.
다른 휴양림들과는 다르게, 두루웰은 고기 구워먹는 곳이 한곳에 몰려있어서 조금 신선했는 듯.

 

  • 그리고 여느때와 똑같은 음주생활... 못해도 한주에 한번씩은 사진이 있다 ㅋㅋ;;

트레이더스에서 가격이 엄청 싸길래 샀던 싸구려 보드카. 맛이 너무 없어서 어떻게 먹을까.. 하다가 일본에서 생활중인 친구가 오미아게로 줬던 원액이 있어서 섞어먹었다. 원액 덕분인지 상당히 맛있게 먹었는 듯.

 

  • 게임적으로도 차근차근 계단을 올라가는 느낌이 들었다.
    • IIDX 입문 때 Blue Rain 黑채보 다음으로 꼭 해보고 싶었던 Time To Air 黑 채보를 드디어 클리어했다 :)
      (https://youtu.be/S9vp_VctfG4)
    • 31 EPOLIS 즈음 부터 갑작스레 꽂혀버린 SHADE도 드디어 풀콤보를 달성해보았다.
      (https://youtu.be/UpA6LTrhcII)
    • 팝픈뮤직 쪽에서는 고점이 잘 뚫리지 않아, 여느때처럼 밑판 다지기를 열심히 한 듯.
      • 이때즈음 갑작스레 WORLD TOUR 시리즈에 너무 꽂혀서, 한동안 갈때마다 플레이했었다.
        (https://youtu.be/8UrtDqOqbtI)
    • SDVX에서 입문 시절 정말 클리어가 어려웠던 노래를 PUC 할 수 있었다.

당시에는 점수내기가 참 어려웠는데, 몇년이 지나고 한번씩 플레이하니 채보가 참 재밌는 느낌.

 

 

 

7월

  • 부모님이 어딘가로 좀 길게 여행을 가시게 되어서, 집에서 이런저런 요리를 시도했었다.
    • 유튜브에서 한번 봤던 home-made shawarma를 따라서 만들어도 보고, 냉동 가라아게 가지고 가라아게동을 해먹어보고...

01234
당시 직접 만들어서 먹었던 샤와르마. 확실히 시중에서 판매하는 또띠아보다 씹는 질감이 훨씬 좋았던 기억이 난다.

 

  • 동아리 내의 같은 과 톡방에서 스터디 인원을 모집했다.
    • 주제는 LLM, AI Agent.
    • 석사 졸업 즈음 부터 트위터 기술 계정에서 자주 접하면서 조금씩 관심은 생기긴 했었는데, 시간이 지날수록 기술이 너무 빠르게 발전하는 느낌도 들었고
      + AI 관련 직무들도 대부분이 해당 기술 관련된 직무를 모집하기 시작했기에 지금이라도 시작해보자 했다.
    • 혼자서 해볼까... 싶다가, 나처럼(?) 기술 연구를 하고싶어하는 후배들이 있지도 모르니 스터디를 한번 주최해보자 해서 스터디를 모집했다.
    • 톡방 성격상... 나를 포함한 동기 몇몇과 2~3학번 밑의 후배들이 주로 수다를 떨다보니, 그 아래의 후배들은 큰 관심을 가지지 않을 거라 생각했었다.
      • 그런데, 정작 글을 올리고 보니 올해 신입생으로 들어온 25학번 후배부터 해서 21학번 후배까지 3명정도 되는 어린 후배들이 참여의사를 밝혔고, 동기 한명과 친한 2 학번 밑의 후배가 참여 의사를 밝혔다.
      • 다들 조용하긴 했어도, 그래도 이런 분야에 관심을 가지고는 있었구나... 를 새삼 느끼게 되었다.

당시 카톡방에 올렸던 스터디 모집 공지글

  • 이 외에는 특별한 일 없이 아르바이트를 하고, 오락실 지인들과 함께 화정에 생겼던 '산다이메 토리메로'라는 일본의 닭꼬치 이자카야 체인점에서 음주.
    • 안주들 가격대도 나름 괜찮았는데, 나중에 들어보니 몇달을 못 버티고 폐점했다고 한다...
    • 이 날, 동아리의 말썽인 후배 하나가 참 밉보이는 행동을 해서... 여태 참으면서 쌓였던 불쾌한 감정이 술을 먹다보니 폭발했던 것 같다. 자정을 넘어서 장문의 카톡으로 한소리(?)를 하고...

토리메로 에서 먹었던 메뉴. 뭔가 참 말그대로 '적당한 가격' 이라는 느낌이 들긴 했다.

  • 이외에도 동아리 후배들이랑 같이 오락실에서 놀고 음주하고... 나름 재밌게 보낸 느낌.

 

  • 게임적으로는 IIDX쪽에서 나름(?) 발전을 한 느낌이었다.
    • 년 초에 개전에서 빨간약을 먹은 뒤로, 간간히 스크래치 채보들을 플레이.
      이런저런 노래들을 하드클 했는데, Level 3가 잡혀져서 정말 당황스럽기도 하고 기뻤었다. S 3호 :)
    • 팝픈뮤직에서는 새로 해금되었던 MAX KARAI라는 노래 덕분에, 정말 오랫만에 팝픈 클래스가 올라서 기뻤었다.
      (https://youtu.be/lOKTjXKwUho)

개인적으로 익하클을 하고 싶었던 TRIP THE DEEP 부터, Level 3 까지. 기체 상태가 영 좋지않은 주안 CPU에서 플레이 했었는데, 그래도 년초보다는 스크래치 리딩이 얼추 잘 되는 느낌이었다.

 

 

 

8월

  • 광치 휴양림으로 큰형네 가족과 부모님과 함께 여름 휴가.
    • 아..마 기억상 초여름? 즈음에 휴양림 선착순 예약을 했었는데, 당시에 온 가족이 시도했지만 나 혼자 성공해서 뭔가 참 뿌듯했던 기억이 난다.
    • 2박 3일을 묶으며 근처에 있는 조그만한 계곡? 에서 물놀이도 하고, 수육도 삶아먹고 장어도 구워먹고... 

예약에 성공했던 숙소. 몇년전에도 한번 묶었었던 곳이었다.
첫날에 삶아먹었던 수육이랑 두루치기 비슷한 향토음식(?). 맛있긴 했는데 입맛에는 좀 많이 달았던 것 같다.
둘째날에는 숯불에 구워먹고, 사왔던 장어도 함께 구워서 먹었다.

 

  • 여태까지 노량진을 자주 가보지를 않기도 했는데, 동아리 후배들을 만나러 가는 김에 이참에 컵밥을 먹어보고자 했다.
    • 그런데 하필 가는 날이 장날이라고, 수도권 쪽에 집중호우가 와서 전철이 운행을 하지 않았었다 :(
    • 결국 버스를 타고 서울역 까지 갔는데, 가는 길에 길이 침수된걸 보니 뭔가 참... 하필 약속을 잡아도 이런날에 잡혔구나 싶었다.

버스를 타고 가는 길에 본 침수된 도로. 참.. ㅋㅋㅋㅋ
그래도 말로만 듣던 노량진 컵밥을 처음으로 먹어보니, 상당히 맛있긴 했다. 가격도 저렴해서 근처에 있었다면 엄청 자주 갔을 것 같은 느낌.

 

  • 여느때와 같이 아르바이트를 하고 지내다가, 돈이 생긴 김에 오랫만에 WINE 25를 둘러보던 중 할인율이 정말 높은 위스키를 발견하고 구매.
    • 이스라엘? 인가 중동 지역 위스키였는데, 인터넷을 찾아보니 면세가보다 훨씬 싸게 나와있어서 바로 구매.

해당 위스키. 지금 와서는 맛이 잘 기억이 안나지만, 그래도 6~7만원 돈으로 먹기엔 상당히 좋은 느낌이었다.

 

  • 평소처럼 방탕한 음주생활을 하다가, 기어이 올것이 왔다. 통풍.......
    • 처음에는 잠을 잘못자서 발이 아픈줄 알았는데, 날이 지나도 발등이 뻐근한게 도통 없어지질 않았었다.
      장난이 아니라 진짜... 발등이 수시로 찌릿거리고 아파서 아침 6시까지 잠을 제대로 자질 못했었다 :(
    • 설마 아니겠지... 아니겠지.. 하면서 얼음찜질을 하면서 2~3일을 뻐기다가, 결국 병원에 방문.
    • 피검사를 하고 나니, 요산수치가 기억상 6?8? 미만이 정상수치인데, 이거를 조금 넘긴 .6이었나 .8이었었다.
    • 작은형이 분가를 하고 나서 부터 집에 먹을 술이 마땅치 않아, 쌓여있는 맥주만 미친듯이 먹긴 했었는데...
      이게 쌓이고 쌓이고 쌓여서 결국 터졌구나 라는 생각이 들었다 😥
    • 큰형도 예전에 통풍에 걸렸었는데, 너도 올게 왔냐면서 비웃고 이런저런 조언(?)을 해줬다 ㅋㅋㅋ...

당시 처방받았던 약.

 

  • 통풍 약을 처방받고 난 후, 공군사관학교에서 교수사관으로 지내고 있는 후배를 보러 동아리 선/후배, 동기친구와 함께 청주에 방문.
    • 교수사관을 하고있는 후배가 예전부터 언제 술한번 먹으러 오라면서, 오면 술은 무한으로 드리겠다곤 했었다가 이번에 일정을 잡고 방문.
    • 공군사관학교 내부에 있는 외래자 숙소의 방을 2개 잡고, 늦게까지 음주.
    • 통풍에 걸렸다는 소식을 전하니 모두가 참 안쓰럽게 웃던 기억이 난다... ㅋㅋ

당시 교수사관 후배가 관사에서 들고온 술들. 피트를 좋아하는 애라 그런지 피트 위스키가 참 많았다.
선배가 부탁해서 후배가 사왔던 일본 위스키. 난생 처음보는 위스키였는데, 맛은 잘 기억이 안나지만 상당히 맛있었던 거로 기억한다.
정~~말 오랫만에 냉동도 먹었다. 오랫만에 먹어서 그런지 불량한 맛이 참 좋았는 듯.
교수사관 후배가 안에 사슴이 많다곤 했었는데... 진짜로 저렇게 바로 보일줄은 진짜 상상도 못했다 ㅋㅋㅋ
나와서 해장 겸 먹은 뼈대짬뽕? 뭔가 특이한 느낌이긴 했다.

 

  • 여느때처럼 연신내에서 동아리 후배들과 놀다가, 다같이 술한잔을 하자고 해서 이사오기 전에 가끔씩 들렀던 족발집에서 음주.
    • 통풍에 걸린것 때문에 평소처럼 1L 맥주를 파는 술집을 가지 못해서, 대안을 찾다가 족발집으로 결정.

이사 전부터 오랫동안 있었던 연신내 족발집. 정말 오랫만에 와도 가격이 참 저렴해서 좋았다.
정신을 차리고 보니 어느샌가 모두가 너무나 과음을...

 

  • 게임적으로는, 뭔가 한번 정체기가 온 느낌이었다.
    • 팝픈뮤직을 주력으로 하다 보니, IIDX는 뭔가 처리력 보다는 중저렙/동치 판정만이 올라간 느낌.
    • 팝픈뮤직에서도 고점이 잘 뚫리질 않아, 중저렙에서 쥬크박스를 돌리면서 47~48을 많이 한 것 같다.
      • IIDX에서 먼저 접해서 너무나 친숙한 Blind Justice를 드디어 S를 달성해서 기뻤었다 :)
        (https://youtu.be/Q9VrAkk1nUY
      • 오랫만에 HIP ROCK 시리즈를 플레이하니, 점수가 간만에 올라서 기뻤던 기억이 난다.
        (https://youtu.be/3CpofJFdEzE)

 

 

 

9월

  • 스터디의 첫번째 스터디(배경지식 스터디)가 끝나고, 두번째 스터디(논문 review)의 시작 준비를 했다.
    • 나와 학부연구생을 하고 있는 후배 이외에는 모두가 논문을 읽어본 경험이 없어서, 논문을 어떻게 읽는지 간략하게 정리하면서 예전에 deep-dive 했던 GCN, GraphSAGE, survey paper를 다시 훑어보며 스터디 페이지에 읽는법을 정리해두었다.
    • 2년?정도가 지나서 review 했던 논문을 다시 보니... 뭔가 참 열정 넘치게 연구했었구나 라는걸 다시 한번 느꼈었다.

당시 스터디 페이지에 정리한 내용

  • 추석에 맞춰서 올해도 시골로의 벌초가 예정되어 있었는데, 올 5월인가 6월에 미리 잡아둔 약속이 있어서 불가피하게 참석을 못했다.
    • 일본에서 일하고 있는 동아리 동기 친구가, 9월달에 다시 한번 한국에 잠깐 온다고 하여 모일사람 모여서 먹고 마시자고 했기에... 이번에는 부모님도 그리 오래전에 잡아둔 약속이니 별수 없지라고 이해해 주셨다 :)
    • 동아리 선배가 차를 끌고 오셔서 다함께 가나안덕에서 밥을 먹고, 마침 일산 호수공원에서 전통주 축제가 있어서 구경을 좀 하다가, 우리 집으로 돌아와 음주.
    • 다음날엔 친구가 샤브올데이를 한번도 안가봤다 해서(나도 가본적이 없었지만), 삼송역 앞쪽에 새로 생긴 샤브올데이에서 점심을 먹었다.
      • 샤브샤브에 간단한 바이킹 식 조촐한 뷔페로 구성되어 있었는데, 가격이 가격인지라 나는 굳이.. 라는 생각이 들었는 듯.

01234
가나안 덕에서 밥을 먹고, 호수공원에서 열린 전통주 축제도 구경. 이번에도 친구가 여러 오미아게를 가져다 주었다. 집앞 정육점에서 술안주거리를 사고, 음주하고, 다음 날 해장 겸 점심으로 간 샤브올데이.
01
아마 기억상 작년?즈음 일본여행을 다녀오고 나서 아주르레인 로손 콜라보가 열렸었다. 당시에 친구에게 하나 구매를 부탁했었는데, 서로 잊고지내다가 이번에 들고와달라 해서 건네받았다.

  • 그리고 또다시 본격적인 하반기 시즌이 시작되었다.
    • 직무가 조금 맞아보이는건 최대한 많이 지원해보면서, 자소서도 정신없이 쓰고...
    • 이번에 처음으로 말로만 들었던 AI역검을 봤었다.
      • 신기하게도 서류전형 다음에 AI역검을 보는게 아니라, 지원했던 곳 거의 대부분이 서류전형과 AI역검을 같이 봤었다.
      • 경험담?은, 그래도 확실히 일반 대기업 인적성 검사(CJT, SKCT, KT인적성 등...)보다는 그래도 나름 재미(?)는 있었는 듯.
        도대체 이걸 왜 공부하나... 싶은 일반 인적성 검사와는 다르게, 그래도 약간 게임식으로 진행하면서 영상면접도 체험해보고, 무엇보다 끝나고 나서 결과분석을 볼 수 있었던게 참 마음에 들었던 것 같다.
    • 알바를 다니면서 여러군데 서류를 쓰고... 결과를 기다리면서 그래도 이번에는 좋은 결과가 나오겠지 하면서 조금은 조마조마 했던 것 같다.
  • 음주도 여느때처럼 적당히 한 듯 하다.
    • 마트를 둘러보다가, 삿포로 생70에 적혀있는 가타카나에 '퓨린' 이라는 글자에 '오프'라는 글자가 적혀있어서 도대체 뭘까 하고 찾아보니 퓨린질?을 70% 줄였다는 것을 알게되었다.
    • 놀랍게도 3~5캔을 마셔도 다음날 발작이 하나도 없었던 것... 앞으로의 인생 맥주가 될 듯 하다 :)

확실히 다른 맥주들에 비해 맛?이 훨씬 덜 묵직하긴 한데, 그래도 제로맥주들 보다는 목넘김도 좋고 맛도 좋아서 대만족 :)

 

  • 게임적으로 보면 팝픈뮤직을 정말 열심히 했었던 것 같다.
    • 47~48레벨을 많이 플레이하면서, 자잘하게 AAA를 많이 찍어낸 듯. 48에서 노래도 정말 친숙하고 좋고 채보가 정말 재밌어서 자주 플레이하는 Little Prayer를 드디어 AAA 달성했었다.
      (https://youtu.be/z9-Z-b1Uyt8)
    • 플레이 스타일이 36~39 즈음 부터 손풀면서 시작해서 한레벨씩 올라가는데, TЁЯRA 유닛에서 좋아하는 노래 중 하나를 드디어 S를 볼 수 있어서 참 기뻤다. 
      (https://youtu.be/46xDt9KAths)
    • 팝픈 뮤직을 참 열심히 해서 그런지, 침체기가 와서 그런지 IIDX 쪽은 참 열심히 안하긴 한 듯.
      • 이벤트도 전부 완주하지 못한게 아마 군시절 가동했던 SINOBUZ, CANNON BALLERS 이후로 처음이다...
      • 이번에는 특이하게도 9월달에 버전 업데이트를 했었다. 통상으로 나온 노래들 중 정말 마음에 드는 노래가 있어서 항상 플레이 하는 듯.
        (https://youtu.be/rEAehQbOeBo)
    • 기억상 7~8월즈음 부터 IIDX의 침체기를 느끼고, BMS를 다시 건들기 시작했던 것 같다.
      • 처리력 고점을 높여보고자 sl5까지 순회를 마치고, sl6~sl7을 슬슬 건들기 시작.
      • 그래도 어찌저찌 ★9에서 하드클리어를 하나 늘려보고 (https://youtu.be/wL26DGkUnKo),
        ★10에서 목표로 잡았던 Angel Dust도 클리어 해보고 (https://youtu.be/7FajdPuypsY),
        ★12에서 정말 오랫만에 새로운 클리어가 하나 늘었었다.

3번째 ★12 클리어. 점수와 판정은 많이 슬프긴 한데, 그래도 클리어가 하나 늘어서 기뻤다 :)

 

 

 

10월

  • 8월달에 큰형네 가족과 광치휴양림으로 휴가를 갔을때, 큰형수가 베트남을 한번 가보자는 이야기를 하셨었다.
    • 그래서 어찌저찌 예약이 되고, 일정이 잡히고... 어쩌다 보니 난생 처음으로 동남아 여행을 가게 되었다.
  • 첫날엔 현지시간으로 00시? 즈음 깜란 국제공항에 도착. 확실히 날씨가 조금 덥기는 했었다.
    • 형수가 콜밴 같은걸 예약해두었어서, 부모님과 형수와 조카들과 함께 차를 타고 잠깐 눈을 붙일 숙소로 이동.

묶었던 호텔에서의 조식. 반찬들이 뭔가 친숙한 맛이 났다.

  • 그렇게 둘째날에는 형수가 예약했던 풀빌라?풀펜션?에 가기 전, 간단하게 시내 투어를 했다.
    • 롱선사를 가보고, 롯데마트(!)에 가서 먹거리와 술을 사고, 담시장에 가서 점심을 먹고 시장 구경을 하고...

숙소에서 나와서 찍은 근처 사진. 뭔가 확실히 미디어에서만 보던 동남아 거리를 실제로 보니 느낌이 색달랐다.
012
숙소에서 전용 콜밴을 타고 처음 간 롱선사. 확실히 한국/일본/중곡의 사찰들과 비슷하면서도 조금은 다른 느낌이 들었다 // 롯데마트에서 찍은 신기한 초코파이 사진.
01234
형수가 근처 맛집을 찾아보라 해서 찾았던 가게. 확실히 현지식 느낌이 많이 났는데, 맛 자체는 거부감이 전혀 없어서 정말 배부르게 먹었던 기억이 난다. 부모님도 입맛에 잘 맞으셨다 해서 다행이었다 :) // 가게에서 밴을 타고 5분?내외로 가니 나온 담시장. 가서 모자도 사고, 크로스백도 사고, 물건들이 확실히 저렴해서 참 놀라웠다.

 

  • 그렇게 볼일을 다 보고, 형수가 예약한 리조트? 로 이동.
    • 가기 전까지는 주변이 뭔가 휑~ 해서 이런데에 있는게 맞는건가.. 싶었는데, 리조트 촌이라도 되었는지 인근에 비슷한 건물들이 많아서 느낌이 좀 색달랐다.
    • 도착하고 보니, 형수가 예약을 일반등급? 으로 안하고 한단계 위인 LEVEL 등급? 으로 했다고 하여, LEVEL 라운지에서 체크인을 진행한다고 무슨 조그만한 밴(기억 상 톡톡? 으로 불렀던 것 같다)을 타고 다시 이동.
    • 라운지에는 상시로 과일류와 간단한 먹거리, 술/음료가 무제한 제공이었는데, 특정 시간대(기억상 아마 오후4시~7시 였던 것 같다)에는 종류들이 늘어난다고 했다.

012
맨처음 도착했을때의 메인 로비, 리조트 안에서의 이동수단인 미니밴(톡톡?), LEVEL 라운지에 있었던 먹거리와 마실거리들.
묶었던 숙소. 층도 2개에, 앞에 전용 풀이 있었다.

  • 저녁식사는 간단하게 LEVEL 라운지에서 먹고, 숙소로 돌아와 쉬면서 롯데마트에서 사왔던 술들을 먹고 룸서비스를 시켰다.
    • 여태까지 룸서비스 라는 것 자체를 시켜본 적이 (기억상) 없는데, 이런데를 따라오니 이런거도 거리낌없이 시켜볼 수 있어서 참 색다른 경험이었는 듯.

0123
특정 시간대가 되니 확실히 먹거리가 많이 늘었었다. 나름 조촐하게(?) 먹으면서, 술을 같이 먹으니 참 배부르게 먹었는 듯. // 마트에서 샀던 RTD와 룸서비스. 조카가 치킨이 먹고싶다 하여 한국식 치킨을 시켰는데, 생각보다 맛있어서 놀라웠다.
라운지에서 특정 시간대에만 나오던 술 중 하나. 베트남에서 만든 진이라고 했는데, 상당히 맛있어서 이것만 먹었던 기억이 난다.

  • 그렇게 한 3일 정도를 숙소에서 푹 쉬면서, 정말 말 그대로 '힐링 여행'을 잘 다녀온 듯 하다.
    • LEVEL 등급?만 사용할 수 있는 레스토랑에서 조식도 먹고, 리조트가 소유한 개인 해변?에도 가보고, 조카를 데리고 숙소의 풀장 & 리조트 내의 공용 풀장에서 같이 물놀이도 하고, 형수가 예약했던 마사지 샵에 가서 마사지도 받아보고...
    • 무엇보다 많이 놀라웠던 건, 숙소에서 '배달음식'을 시켜먹을 수 있던게 신기했다.
      • 배민같은 배달 어플이 따로 있어서, 그걸 설치하고 보니 현지식, 한식, 카페, 과일 등... 참 먹거리가 많았다.
      • 물론, 음식은 메인 로비쪽에 있는 정문 출입구까지 나가야 했다 ㅋㅋㅋ 숙소에서 거리가 꽤 있어서, 갈때마다 톡톡?이라는 미니 밴을 타고 이동했다.

012
LEVEL 라운지만 사용할 수 있다는 레스토랑에서 먹은 조식. 신기하게도 (뷔페식으로 있는 음식 제외) 자리에서 직원이 주문을 받고, 요리사가 만든 후 자리까지 서빙해주었다. 에그베네딕트 라는 음식을 여기서 처음 먹은 듯... // 먹었던 반미. // 체크아웃 날 갔었던 공용 레스토랑. 확실히 사람이 참 많기는 했다.
012
숙소에 같이 딸려있는 개인 풀장, 리조트 공용 풀장. 날씨가 조금 습하고 더웠는데, 물 온도는 참 적당하게 시원했다. // 개인 해변?에서 찍어본 한장 :)
숙소 발코니에서 찍은 한장. 스콜이 좀 있긴 했는데, 아침에 날씨도 좋고 뷰가 너무 좋아서 무의식중에 카메라를 꺼냈다.

 

  • 그렇게 약 5일? 간의 여행을 다녀오고... 하반기를 마저 보냈다.
    • 이곳저곳 지원을 했지만 역시 좋은 소식..은 도통 들려오지가 않았다 :(
    • 그래도 작년에 지원했던 CJ 계열사의 동일한 직무가 있어서 9월에 지원서를 작성했었는데, 문항이 완전 똑같아서 내심 기대를 했더니 좋은 소식을 들려주어서 많이 기뻤다 :)
    • 작년의 교훈을 토대로 삼아, 실물책을 구매하지 않고, 교보문고 e북을 구매해 태블릿으로 문제를 풀면서 준비를 했다.
    • 그.....런데, 문제는 도표해석 부분이 작년과는 다르게 5분이 줄어들었었다.
    • 도표해석 부분 문제를 풀면서 최대한 절반은 풀어보도록 했다.
    • 시험 당일날, 문제를 풀다보니 그래도 작년보다는 많이 발전한 느낌은 들었는데, 도표해석 부분은 기억상 8문제 정도 풀었던 것 같다. 아무래도 시간 압박이 참 컸는 듯...
      그리고 수리문제에서 수열추리가 한문제도 안나와서 배신감이 많이 들었던 것 같다 :(

다행히도 작년과 지원서 문항들이 거의 똑같아서, 수정을 거의 안하고 제출했었다. 그래도 어찌저찌 하반기 첫 서류통과라 그런지 기분이 좋았다.

 

  • 여행을 다녀오고, 하반기도 마저 우당탕탕 보내고, 알바를 다니고... 뭔가 조금은 정신없이 10월을 보낸 듯 하다.

 

  • 게임적으로는 뭔가... 고점이 크게 뚫렸다기 보다는 저점을 조금씩 올린 듯 하다.
    • 팝픈뮤직에서 47 입문때즈음 부터 정말 마음에 들었던 CHINA ROCK을 5 BAD로 클리어 할 수 있었다.
      (https://youtu.be/YneA1Hchjx8)
    • IIDX는 뭔가 저점 자체가 잘 오르긴 한 듯. 전작에서 AAA 달성에 여러판 걸렸던 노래들이 바로바로 AAA가 나와서 소소하게 기뻤었다.
    • BMS에서는 sl7을 건드리기 시작. 뭔가 고레벨 존에 오니 조금은 매니악한 노래/채보가 많기는 한 듯...
      (https://youtu.be/0e-750FdcAQ)

 

 

 

11월

  • 평소처럼 알바를 하고, 오락실을 가고... 뭔가 루틴이 고정되다 보니 시간이 엄청 빠르게 지나가는 느낌이 들었다.
  • 어머니가 친구분과 함께 스페인 여행을 가시고, 아버지가 대학교 동창분들과 양평으로 짧게 여행을 가신 김에, 오랫만에 후배와 함께 술을 먹었다.
    • 처음에는 우리 집에 불러서 음주를 하려고 했는데, 후배가 움직이기 귀찮다 하고 + 자기 집으로 오면 히비키를 먹여준다고 해서 당장 달려갔다 ㅋㅋㅋ
    • 거진 1여년? 만에 봐서 그런지 너무 반가웠고, 늦게까지 수다떨면서 정신없이 먹었던 것 같다.

후배 집에서의 음주. 비싼 술은 확실히 맛있다.

  • 어머니가 여행을 가신 동안, 큰형네와 작은형네가 집에 방문해서 어쩌다보니 어머니 없는 가족 외식을 했다.
    • 아버지가 집 근처에 새로 생긴 고기집이 있다고 하셔서 갔는데, 세트 메뉴가 뭔가 조촐한 것 같으면서도 양이 꽤 많아서 배불리 먹었던 기억이 난다.
    • 고기 자체의 양은 그렇게 많지 않았던 느낌인데, 종류가 다양하기도 하고 고기마다 맛이 참 좋았던 것 같다.

01234
가게에서 먹은 세트메뉴. 육회와 샐러드가 참 맛있었던 기억이 난다. 고기류는 맛있긴 한데, 양이 조금씩 여러개가 있어서 그런지 맛은 좋았는데 살짝 아쉬운 느낌이 많이 들었는 듯.

 

  • 하반기가 얼추 지나가면서, 공고들도 많이 줄어들었지만 그래도 지원해볼 수 있는 분야는 최대한 지원해봤다.
    • CJ 외에 다른 기업들도 계속해서 불합격을 던져주던 사이, 한번 지원이나 해보자 했던 한 중소기업의 서류가 통과되었다는 소식을 받았다.
    • 이번 하반기에 처음으로 넣어본 중소기업이긴 한데, 공고문에는 'AI 프로젝트 경험 5개 이상'이 자격 요건이었다.
      석사과정 당시 진행했던 프로젝트가 3개 뿐이었지만 그래도 넣어나 보자 하는 마음에 지원을 했었는데, 이게 합격 소식을 들려줘서 참 당황스러우면서도 기분은 좋았었다 :)
    • 다음 전형으로 코딩테스트를 봤는데... 1시간에 3문제가 나왔다.
    • 누가 봐도 선택과 집중을 하는 것이긴 했는데.... 제일 만만해 보였던 1번 문제를 구현하다가, 석사과정 당시 졸업연구를 하면서 엄청 자주 썼었던 pandas 기능이 있었는데, 이걸 사용하지 못해서 docs를 뒤적거리다가 그냥 포기하고 나왔다 :(
    • 결과는 뭐... 0솔인데 좋은 결과가 있을리가 😅

하반기에 처음 넣었던 중소기업에서의 합격 메일. 한번 찔러나보자 했는데 이게 얻어걸려줘서 뭔가 기분이 참 묘했었다.

 

  • 게임적으로는 지난 달처럼, 고점보다는 저점이 조금 더 오른 느낌이었다.
    • IIDX에서 군 전역 후 정말 즐겨했던 Rootage의 테마곡을 AAA 달성할 수 있었다.
      (https://youtu.be/cdTqjel7g8w)
    • IIDX에서 항상 AAA 마이너스 한자리를 봤던 노래를, 배치가 운 좋게 잘 얻어 걸려줘서 바로 AAA를 달성했다. 정말 기뻤다 :)
      (https://youtu.be/BoN72bpd3IY)
    • 팝픈뮤직에선 44레벨의 Blow Me Up을 드디어 S를 보았다. 판정도 짠데, Sota Fujimori 식 박자가 참 골치아프긴 했다.
      (https://youtu.be/pmf924SAhYs)
    • 팝픈뮤직 46레벨에서 S를 4개나 볼 수 있었다 :)

신곡(UPPER채보)과 함께 S를 노렸던 2개, 그리고 친구들의 추천으로 그날 접했던 노래.

 

 

 

 

12월

  • 작은 형네가 임대주택?의 계약이 만료가 되어, 우리집의 예전 작은형이 썼던 방으로 작은 형과 작은 형수가 함께 이사를 오게 되었다.
    • 한 3일 정도 형네 집에 가서 이사짐을 같이 옮겨주고, 집정리를 도와줬다.
    • 거진 1년 반? 정도 넓은 집에서 부모님과 나만이 지내다가, 작은 형네 가족이 이사를 오니 뭔가 참 북적이는 느낌이 들긴 한다.
    • 그래도 작은 형이 돌아온 덕분에, 오랫만에 형이랑 같이 새벽 늦게까지 음주를 하고, 형이 들고있는 여러 위스키들을 다시 맛보게 되어서 기뻤다 :)

새벽 4시에 찍은 음주의 흔적.

  • 알바를 하고, 오락실을 다니며 여느때처럼 지내던 중, 동아리 후배 겸 화정 오락실 지인분이 망년회를 하자고 해서 지인 집에 방문.
    • 친구가 오미아게로 가져다 줬던 레몬 사와를 집에서 나 혼자 먹기도 하고, 도통 먹지를 않아서 이참에 들고갔는데, 그날 거의 다 비워버렸다 ㅋㅋㅋㅋ....
    • 부모님께는 자고 올지도 모른다 했는데, 지인분이 새벽 2시즈음 뻗어버리시는 바람에, 후배와 함께 나와서 택시를 타고 귀가.

01
음주 전/후. 다시봐도 먹은 양이 참....ㅋㅋㅋㅋㅋ 그래도 취미가 맞는 사람 몇몇이 모여서 술을 먹는게 오랫만이라 그랬는지, 술이 너무 잘들어가긴 했다.

  • 나고야에서 일하고 있는 동아리 선배가 인원을 모아서, 오랫만에들 함께 만나서 점심을 먹었다.
    • 하이디라오 를 갔는데, 모두가 처음 가보는지라 이것저것 시켜서 먹고 수다도 떨고...
    • 대전에서 일하고 있는 친구 겸 후배가 성심당 딸기시루 케익을 사오고, 모인 날에 후배 하나가 생일이라 직원들이 생일축하 노래도 불러주고, 식사를 다 하고 케익을 먹었다.
    • 몇몇 인원을 빼고 거의 3~4년만에 만나는 지라... 너무 반갑고 다들 잘 지내고 있는 것 같아서 좋았다 :)

01
하이디라오. 오기 전까지는 당연히 무한리필 집인줄 알았는데, 소스부터 해서 모든게 다 단품주문이었다;; 다같이 룸잡고 모여서 먹는거 아닌 이상 다시 갈일은 없을듯 ㅋㅋ... // 대전에서 온 성심당 딸기시루케익. 소문대로 확실히 내용 건더기(?)가 참 꽉꽉 차있었다.

 

 

  • 하반기가 얼추 마무리 되었다.
    • 이전에 합격했었던 중소기업 외에도 3군데?4군데? 정도를 지원했었는데, 한곳은 아예 연락도 오지 않고 나머지는 전부... :(  
    • 결국, CJ와 중소기업 한 곳을 제외하고 전부 서류에서 떨어졌다. 뭔가 참.... 시장이 불안한건지, 내가 작성하는 서류가 문제인건지, 스펙이 문제인건지...
    • 너무 간절한 마음이 들어, 석사생활 당시 한 회사와의 협업 프로젝트를 할 때 회사의 대표님(겸 교수님)께서 석사생활 내내 프로젝트 했던 건에 대해서 경력으로 활용해도 좋다고 말씀해 주셨던게 기억이 났었다.
      • 그래서 이를 활용해보고자 경력 3년이상 인 경력직 공고도 한번 넣어봤었는데, 역시나 가차없이 떨어졌었다 😅
    • 채용사이트를 돌아다니다가 우연히 스타트업 규모의 중소기업을 하나 발견했는데, 비전도 상당히 좋아보이고 사업 영역도 상당히 마음에 들어보이고, 무엇보다 모집하는 직무의 전공이 내 전공과 거의 90% 가까이 일치하는 곳을 하나 발견했다.
      • 중소기업(이라고는 하지만 ㅈ소기업..)을 2~3년 정도 다녔던 고등학교 동창 친구는 그래도 중소는 최대한 피하는게 좋다.. 라고는 하는데, 그래도 국제 컨퍼런스에 논문도 제출하고 억셉되었던걸 보면 허수는 아닌 느낌이 들긴 하다.
      • 채용사이트에서는 공고가 이미 지나있지만, (아직까지는) 회사 홈페이지에 상시 공고로 올라와 있어서, 포트폴리오를 다시 제대로 만들어 본 후에 한번 지원해보고자 한다.

 

  • 게임적으로는... 잘 모르겠다. 예전보단 고점이 조금씩 뚫리는 느낌이긴 한데, 체감히 확 와닿지가 않는 듯. 저점은 확실히 올라가고 있는게 느껴졌다.
    • IIDX에서 약간 처리력 수련용? 으로 자주 플레이하는 CADENZA를 드디어 AA 달성했다 :)
      (https://youtu.be/gJ9sF2W515I)
    • 별 생각없이 골랐던 DEEP ROAR가 배치도 괜찮게 나오고, 바로 FULL COMBO가 나와서 참 놀랐다.
      (https://youtu.be/QHjw6RHLQkg)
    • IIDX 아레나가 시작했는데... 하필 첫번째 해금곡이 최근에 삭제되었던 evergreen이라, 피눈물을 흘리면서 해금을 했다 :(
      A4라서 그런지 + 첫 아레나라 그런지 선곡들이 참 더럽고, 몇판 이기면 바로 A3랑 매칭되서 포인트 쌓기가 참 힘들었다.
    • 팝픈뮤직에서는 저점이 확실하게 오르긴 한 느낌. 최근에 해금했던 High & Low가 노래도 너무 신나고 채보가 너무 재밌어서 항상 플레이하는 듯.
      (https://youtu.be/xN7c3qa9c7k)
    • 오랫만에 バッドエンド・シンドローム(배드 엔드 신드롬)을 다시한번 기갱+클리어 해보고 (https://youtu.be/2H56kwotP2s),
      계단이 잘 쳐지는 날에 드디어 라크리마를 클리어했다... 이제 점수만 올리면 될 듯.
      (https://youtu.be/L1vG5id9tD8)
    • 크리스마스 날? 인가 연말에 갑작스레 SDVX가 버전 업데이트를 한다고 해서, 발키리 기체에서 플레이.
      점수체계가 세분화 되어서 그런지, 어떤걸 골라서 클리어해도 볼포스가 참 많이 오르는게 신기했다.

이래서 아레나 돌리기가 진짜 싫다....
그래도 좋은 노래를 다시 챙겨왔으니, Now and Forever가 나올때까지 절대 돌리지 말아야겠다.
발키리 기체에서 하니 바로 AAA+가 나와서 좀 당황스러웠다.

 

 

 

 


 

글을 적으면서 되돌아보니 뭔가 참... 알바를 시작하면서 부터 시간이 빠르게 지나간 느낌이다.

 

작년처럼 가족과 보내는 시간도 많이 늘었고, 인생 처음으로 동남아 여행을 가서 제대로 힐링하고 오고....

 

연말에 작은 형네와 같이 살게되면서, 조용했던 집이 조금은 북적북적 해지니 (부모님 말을 빌리자면) 사람 사는 집 같은 느낌이 나기는 한다 ㅋㅋㅋ

 

커리어 적으로는 흠...

작년처럼 글쎄 정도는 아니고, 자소서에 문제가 좀 있는것 같은 느낌은 들었다.

작년과는 다르게 작성하는 시간을 조금은 줄이고자 ChatGPT나 Gemini에게 직무소개, 만들었던 CV, 프로젝트 기술서를 던져주고 초안을 한번 작성해봐라.. 한 다음에 작성한게 몇몇개 있기는 했는데, 결과는... ㅋㅋㅋㅋ

친구의 말을 들어보니, 요즈음 걸러내는 기술이 좋아져서 다 걸린다고 했다. 그래서 그런지 성의있게 밑에서부터 안쓰고 AI를 좀 많이 활용했다 싶은것들은 전부 떨어졌던 거 보면 ㅋㅋ;;;

이런 AI 활용도 조금 문제였던거 같긴 한데, 올해 석사를 졸업한 실적 괜찮은 동아리 후배도 1~2곳 빼고 전부 서류에서 탈락하는걸 보니 그만큼 시장이 얼어 붙은건지... 잘 모르겠다.

직무에서 몇명을 뽑는지도 모르고, 경쟁률이 대충 얼마나 되는지도 모르다보니... 

 

위에서도 작성했는데, 눈여겨 보고 있는 스타트업 규모의 중소기업의 공고가 닫히기 전에(언제 닫힐지도 모르지만...), 프로젝트 포트폴리오를 다시 빠르게 만들어서 한번 지원해보려고 한다.

별 생각 없이 사이트를 돌아다니다가 발견한 것 치고는 사업영역도 상당히 마음에 들고, 업무-전공 직무도 거의 90%이상 fit 하고... 다만 흠이 있다면 위치가 경기도 구리시 인지라, 된다고 하면 자취방을 구해야 할듯 ㅋㅋ...
설레발을 많이 치기는 하고 있지만, 그래도 좋은 소식을 들려줬으면 좋겠다 ㅎㅎ...

공기관에서 일하고 있는 친구가 전해준 빨간약
상/하반기 작성한 서류들. 상반기1개, 하반기 2개 뿐인게 뭔가 참..씁쓸하긴 하다.

 

 

게임적으로는 뭔가 만족?까지는 아니고, 그렇다고 불만족까지는 아닌 느낌. 중간과 만족의 사이인 듯 하다.

어찌저찌 IIDX에서도 만족한다 라는 성과(Level 3)를 보기는 했지만, 게임을 10년넘게 했는데 개전을 못땄던 충격이 아직도 잊혀지지가 않는다 ㅋㅋㅋ...

팝픈뮤직은 어느정도 만족스럽기는 한 듯. 50을 건들지 않고 팝픈클래스 98.00을 달성한건 참 기뻤는데, 그 후로 고점이 잘 뚫리지 않아서 47~48을 많이 하다보니 오히려 저점이 확실하게 오른게 좋기는 했다.

이왕이면 고점도 같이 눈에 띄게 올랐으면 더 좋았을듯...

IIDX에서 빨간약을 심하게 먹고 BMS를 다시 (이전보다는 자주) 건들면서, 그래도 sl7, ★13 까지는 얼추 비벼볼 수 있는게 참 장하게 느껴지긴 했다.

 

 

어찌저찌 2025년도 이렇게 우당탕탕 지나가게 되었다.

상반기-하반기를 정신없이 보냈다는걸 핑계로, 올해 블로그 포스팅이 4개밖에 안된게 뭔가 참... ㅋㅋㅋㅋㅋ 반성해야 할 듯.

 

26년에는 그래도 조금은 달라지고, 좋은 소식이 생겨서 가족과 친구들, 그리고 선/후배에게 한턱 크게 내는 날이 왔으면 좋겠다 ㅎㅎ..

 

내년에도 열심히 화이팅 :)

 

 

 

 

E.O.D.

 

이전 PART 링크

 

Parallel and Distributed Graph Neural Networks: An In-Depth Concurrency Analysis (1)

GNN 연구를 하던 시절, mini-batch 실험 이후 본격적으로 들어가기 앞서 survey paper가 있는지 찾던 중 발견한 paper.(당시 간단한 실험을 진행했던 내용과 관련된 포스팅 링크) 내용이 너무 많았던 지라,

happysky12.tistory.com

 

 

당시 시간 상 Data Parallelism 이후 부분(Model Parallelism, Frameworks/Accelerators/Techniques 등)은 review를 하지 않았기에, Data Parallelism 파트를 마저 정리하고자 한다.

(당시 신경쓰던 내용이 mini-batch parallelism 이기도 했고...)

 


 

 

Data Parallelism

Graph partition parallelism 과 mini-batch parallelism 비교.

 

전통적인 DL(Deep Learning)에서의 data parallelism은 보통 입력된 data sample들을 mini-batch에 담아 병렬화를 수행했다.

 

이를 간략하게 짚고 넘어가면

  • 각 worker(GPU)는 자신이 담당한 mini-batch(자신에게 할당된 data sample)를 처리.
  • 부분적으로 model의 weight를 계산, parameter server(centralized distributed training) 또는 AllReduce(de-centralized distributed training)와 같은방법을 통해 다른 worker와 작업 내용을 동기화.

일반적인 Parameter Server - Worker Nodes 구조의 centralized distributed training
모든 worker가 Reduce 연산을 수행하는 de-centralized distributed training 중 AllReduce 방식

 

전통적인 DL에서 data sample(ex. image)은 서로 independent 하다.

→ 즉 병렬화가 비교적 간단하고, 동기화는 model parameter를 갱신할때만 1번 해주면 된다.

 

하지만 GNN은 이것이 어렵고, 복잡하다.

왤까? 이전 포스팅이나 여러 포스팅에서도 언급했던 것 처럼, data sample 간 dependency(의존성)가 존재하기 때문이다.

 

dependency 문제 이외에도, input data 자체가 너무 거대한 경우도 존재한다.

(ex. 한 server에 올리기 힘들 정도의 크기를 가진 community graph 등...)

 

이런 경우엔 mini-batch 사용 여부 또는 방법에 관계없이, 하나의 server가 data를 전부 들고있을 수 없으므로,
graph partition parallelism에 의존해야 하는 경우가 많다.

single large graph를 여러개의 sub-graph 로 분할하여, 각 server에 저장한 후 full-batch 또는 mini-batch training을 수행.

 

 

Graph Partition Parallelism(Full-batch Parallelism)

몇몇 graph는 250 billion개의 노드와 10 trillion개의 edge로 구성되있기도 하고, 각 node/edge에도 아주 큰 (차원 수가 매우 높은) feature vector가 붙어있을 수 있다. (OGB dataset 처럼.)

 

이런 경우엔 단일 서버 메모리에 데이터가 올라가지 않으므로, graph를 서로 다른 worker에 분산시켜야 한다.

 

본 논문에서는 이 방법을 graph partition parallelism이라 명명하는데, 그 이유는 이 접근법 자체가 graph partitioning과 mincut problem에 뿌리를 두고 있기 때문이다.

[graph partitioning]
graph partitioning은 기본적으로 NP-complete problemgraph의 크기가 커질수록 최적의 분할을 찾는 시간은 지수적으로 증가. ⇒ 따라서 최적에 근접한 결과를 내놓는 heuristic한 접근을 해야한다.
(참고링크: https://patterns.eecs.berkeley.edu/?page_id=571)

 

여러 graph partitioning 기법들.

 

위 그림처럼 graph partitioning의 방법을 나눠볼 수 있으며, 방법들을 서로 섞어서 사용할 수도 있다.

 

각각을 살펴보면 다음과 같다.

  • edge [structure] partitioning: edge를 구조적으로 나눠서 node들을 서로 다른 worker에 분산.
    • (probably) 가장 많이 쓰이는 방법이지만, 왜곡된 차수 분포(skewed degree distribution)를 갖는 graph를 나눌 때 많은 통신과 work imbalance가 발생한다. (but it comes with large communication and work imbalance when partitioning graphs with skewed degree distributions.)
      (skewed degree distribution은 long-tail distribution의 다른 말. node들의 degree distribution이 한 쪽으로 몰려있다는 의미. 이전에 작성한 Cora batch testing 포스팅(링크)에도 간략하게 설명해두었다.)
    • 하나의 edge가 하나의 server에 할당, 하나의 edge가 서로 다른 server에 할당. → 즉 edge가 다른 server로 나눠짐으로써 개별 node가 서로 다른 worker에 분산된다.
  • vertex [structure] partitioning: node를 구조적으로 나눠서 edge들을 분산.
    • edge partitioning보단 어느정도 여러 문제점을 커버할 수 있지만, 높은 degree를 가진 node가 많은 worker들 간에 분산되어 있다면 일관성 있게 분산된 node 상태를 유지하는데 큰 오버헤드가 발생한다. (but if a high-degree vertex is distributed among many workers, it may also lead to large overheads in maintaining a consistent distributed vertex state.)
    • 하나의 node가 하나의 server에 할당, 하나의 node가 2개 이상의 server에 할당 → 즉 node가 다른 server로 나눠짐으로써, 해당 node와 연결된 edge들이 분산된다.
  • edge/vertex [feature] partitioning: input feature vector를 분산.
    • 전통적인 분산 그래프 알고리즘에서 node/edge가 스칼라(상수) 값을 가지고 있으므로, feature partitioning은 graph processing 영역에서 별도로 다뤄지지 않았다.
    • edge feature vector, node feature vector가 나눠져서 서로 다른 server에 분산 → 말 그대로 feature vector를 분산시키는것. 단지 그 vector가 edge에 해당하는 feature vector인지, node에 해당하는 feature vector인지의 차이.

결국 partitioning은 graph의 일부분이 다른 server에 보관되어 server 간 communication이 발생할 수 밖에 없다.

 

즉, node 또는 edge가 분할된 경우 graph와 관련된 연산(Scatter, Aggregate)에서 communication이 발생하며, feature vector가 분할된 경우엔 신경망 관련 연산(UpdateEdge, UpdateVertex)에서 communication이 발생할 수 있다.

 

graph partitioning은 보통 full-batch training시, 큰 메모리 요구량을 다루기 위해 사용한다.

→ OGB나 Reddit 같은 single large graph의 경우 single GPU/CPU memory에 upload 하는 것 자체가 거의 불가능한 수준.

 

각 GNN layer에 있는 각 노드의 각 feature에대한 모든 activation을 저장해야 한다. 

이를 위한 (널리 알려진) 방법 중 하나로, distributed memory를 가진 large-scale cluster를 사용하는 것인데, 이를 통해 graph partition parallelism과 함께 결합된 메모리에 방대한 양의 input data를 전달해줄 수 있다.

 

하지만 물론 치명적인 단점이 존재한다.

cluster가 very expensive하고, 잦은 communication으로 인해 model convergence가 상당히 느려진다.

(cluster 환경을 구축하는 것 자체가 현실적으로 expensive...)

 

그래서 보통 graph partitioning을 한다 하면 full-batch training을 하지 않고, 주로 mini-batch training으로 접근한다.

 

 

Mini-batch Parallelism

data sample들이 independent graph라면, mini-batch parallelism은 traditional DL에서의 방법과 거의 유사하다.

본 논문에서는 이런 경우를 independent mini-batch parallelism이라 명명한다.

  • mini-batch는 이러한(independent한) graph sample의 집합으로, 서로 간의 dependency가 없다.
  • molecules data(분자구조 데이터)처럼 data sample들이 서로 다른 크기를 가질수 있는데,
    이러한 경우에는 각 worker 간의 load imbalance가 발생할 수 있다.
  • graph들이 서로 다른 크기를 가질 수 있어도, 이들의 feature vector는 같은 차원을 가짐.
    (data를 build할때 feature vector의 차원을 정해두고 만들기 때문.)

 

대부분의 GNN computation에서 mini-batch parallelism이 어려운 이유는 크게 다음과 같다.

 

  1. data sample 간 종속성이 존재 (dependent mini-batch parallelism)
  2. load imbalance 존재: node들의 degree가 서로 다름
  3. mini-batch를 형성할 때, target node(anchor node)를 선택함에 있어 information loss가 발생
    • traditional DL은 data sample을 random하게 선택해서 mini-batch를 형성한다.
    • GNN에선 anchor node를 random하게 선택하면 아주 낮은 accuracy가 나오기 쉽다.
      → node subset을 랜덤하게 고르게 되면, 이 subset들이 서로 연결이 안되어있을 수 있으며,
      매우 sparse하고 missing edge때문에 Aggregate/Scatter 연산 중에 graph 구조에 대한 많은 정보 손실이 발생하기 때문.
    • 이런 정보 손실 문제를 피하고자, 초창기에 행해진 시도(GCN)는 full-batch training에서 시도가 되었지만,
      full-batch training은 수렴이 느리고 많은 메모리를 필요로 하는 문제가 있다.

따라서, 이런 문제들을 다루고자 최근(논문 작성되던 시기 기준. 2022년)에는 크게 2가지 접근법이 제안되고 있다

 

 

Support Vertices (Anchor node selection, Node-wise sampling, Neighborhood Sampling)

(당시 paper를 리뷰하며 정리해놨던 자료와, 이후 arXiv에 다시 수정되어 업로드 된 paper의 단어?구조가 조금씩 다르다. 당시에는 incorporating support vertices였는데 수정되어 업로드 된 paper에는 직관적으로 neighborhood sampling으로 표기되어 있다...)

 

neighborhood sampling(GraphSAGE, 좌) vs. graph-sampling(ClusterGCN, 우)

 

GraphSAGE로 부터 시작되어, support vertices는 샘플된 target node(==anchor node)들의 이웃 일부을 mini-batch에 추가한다.
(one adds some neighbors of sampled target vertices as so called support vertices  to the mini-batch.)
(→ GraphSAGE에서 mini-batch를 어떻게 형성하는지에 대한 간략한 이야기. GraphSAGE에서 node들 중 anchor node를 선택, anchor node의 $k$-hop 거리의 이웃 node를 추출해 computation graph를 생성한다.)

 

support vertices(support vertex)는 tree(graph)에서 degree가 1인 leaf에 인접해있는 node를 의미하며, 차수가 1인 node에 바로 인접한 node로 정의된다. 여기서는 target node(anchor node)를 기준으로 sample된 node들을 의미.

 

이때 support vertices는 target node의 예측 정확도를 높이기 위해서만 사용되며, 해당 mini-batch에서 target node로 사용되지는 않는다.

→ 각각의 mini-batch에서, target node에 대해 Scatter/Aggregate kernel을 실행할 때, 미리 선택된 support vertices도 함께 고려하게 되고, 따라서 두 연산의 결과가 좀더 정확해진다.

 

target node $v$ 의 support vertices는 target node 1-hop 이웃 뿐만 아니라(그래프의 크기가 클 경우), $k$-hop이웃에서도 선택된다. (GraphSAGE에서 제안한 sampling 기법 이야기.)

 

이러한 support vertices selection은 각각 상황에 따라 달라지며, GraphSAGE에서는 실제 train을 하기 전에 각 layer마다 sample된다.

 

simple한 방법이긴 하지만, 물론 challange가 존재한다.

 

  1. overhead of pre-selection: GraphSAGE의 경우, layer의 수 만큼 sampling step을 수행해 각 node와 각 layer에서 support vertices를 선택해야 한다.
    • 즉, layer의 수 만큼 sampling step을 수행하므로 이 또한 overhead가 발생할 수 있다.
    • 이 문제는 parallelization으로 완화할 수도 있지만, 곱셈 상수 인자에 의해 GNN 계산의 깊이를 증가시킨다. (it inherently increases the depth of a GNN computation by a multiplicative constant factor.)
      → GraphSAGE의 시간복잡도는
      sampling 하는 이웃의 수가 가장 큰 요인, $N^{K}VD^2$ ($N$은 샘플링 한 이웃의 수, $K$는 layer의 수, $V$는 전체 노드의 수, $D$는 feature vector의 차원 수)
  2. neighborhood explosion 
    • neighborhood explosion에 관한 설명. layer를 거칠수록 sample 되는 이웃의 수가 지수적으로 증가하는 문제.
    • 또한, 수 많은 node를 계속 hold하고 있어야 하므로, memory overhead가 발생한다.
    • (최악의 경우) $H$-hop 까지의 모든 이웃을 계속 hold 할때, $O(kd^H)$ 의 상태를 계속 유지하고 있어야 한다. 
      • 몇몇 node들이 해당 mini-batch에서의 target node이고 이미 계속 hold 하고 있더라도, hop 수를 늘리면 target node가 차지하는 비율이 적어질 수 밖에 없다.
      • GraphSAGE는 모든 이웃을 hold 하고 있는 대신 이웃의 일부를 (고정된 수 만큼) sampling하여 이 문제를 완화했지만, 메모리 오버헤드memory overhead가 여전히 큼. (from GraphSAINT paper)

 

 

Appropriate Selection of Target Vertices (Sub-graph sampling)

최근의 GNN mini-batching 연구들은 mini batch를 형성할 target node를 어떻게 적절하게 선택할 것인지에 초점을 두고 있고, 이는 support vertices가 굳이 필요하지 않음을 이야기 하고 있다.

(More recent GNN mini-batching works focus on the appropriate selection of target nodes included in mini-batches, such that support vertices are not needed for high accuracy.)

(즉, 굳이 target node를 설정해서 그 이웃들을 sampling 할 필요가 없다는 의견)

 

한 예시로, ClusterGCN은 먼저 graph의 일부분을 cluster 한 다음, 해당된 cluster를 각각 mini-batch에 할당한다.

ClusterGCN의 접근법 (from CS224W)

 

이 방법은 정보가 손실되는 문제를 어느 정도 완화(완전히 없애는 것은 불가능.)할 수 있는데, 이는 mini-batch에 밀접하게 연결된 node community가 포함되기 때문이다. (because a mini-batch usually contains a tightly knit community of vertices.)

 

또한 이 방법은 clustering 하는 작업이 preprocessing 작업에 반드시 필요하지만, 이 방법은 parallel clustering routine을 통해 병렬적으로 처리하여 시간을 단축 시킬 수 있다.

(DistDGL/PyG에서 graph partitioning을 하는 것 처럼.)

 

 

Discussion

  • graph partition parallelism vs. mini-batch parallelism?
    1. model weight를 update하는 시점의 차이: graph partition은 full batch 후에 update하고, mini-batch는 각 mini-batch마다 update한다.
    2. 주 목적 (primary objective): graph partition은 worker간 communication & work imbalance를 최소화 하는 것이 목적이며, mini-batch는 accuracy를 최대화 하는 target node를 선택하는 것이 목적이다.
    3. 각 node의 할당: graph partition은 모든 node가 각각 partition에 포함되며, mini-batch는 포함될 수도 있고 안 될수도 있다.
    4. sample 간의 dependency: graph partition은 연결된 graph를 다루므로 항상 dependency가 발생하지만, mini-batch는 dependency가 없는 경우도 존재한다. (ex. molecule dataset)

 

 

 

Work-Depth Analysis : Full-batch vs. Mini-batch

좌측 복잡도가 work량, 우측 복잡도가 depth 정도.

 

  • $c$는 layer 마다 sampling 된 이웃의 수를 의미.
  • $k$는 input feature의 차원을 의미.
  • $n$과 $m$은 각각 node의 수, edge의 수를 의미.
  • $d$는 graph 안에서의 최대 degree를 의미.
  • $L$은 layer의 개수를 의미.

 

Work analysis

모든 방법은 공통적으로 $O(Lmk + Lnk^2)$ 의 복잡도를 가진다.

  • 각각은 layer의 수 $L$에 각 layer에서 수행되는 작업의 수를 곱한 것.
    • $Lmk$ 는 layer에서 발생하는 sparse graph operation (Aggregate) → edge를 통한 feature의 message passing
    • $Lnk^2$ 는 layer에서 발생하는 dense nn operation (UpdateVertex) → passing 된 message(feature)를 통해 자신 feature와 mm(matrix multiplication)을 통한 갱신

Mini-batch의 경우는 추가적인 작업이 발생한다.

(전체 그래프에 대한 작업은 full-batch와 같은데, mini-batch에서 각각 실행하고 통합하는 작업이 발생.)

  • support vertices (node sampling): node를 선택하는 알고리즘(sampling algorithm)에 따른 작업량이 존재한다.
    • GraphSAGE, VR-GCN: $O(c^Lnk^2)$, 선택할 이웃의 수를 어떻게 설정할지 와 layer의 수에 따라 작업량이 결정되며, 이는 neighborhood explosion을 일으킬 수 있다.
    • FastGCN: $O(cLnk^2)$, 모든 layer에서 c개의 노드만을 샘플링해 explosion을 완화.
      (Importance sampling(참고링크)을 통해 explosion 문제를 어느정도 완화)
  • selecting target vertices (graph sampling): neighborhood explosion에 영향을 미치는 term이 존재하지 않지만, $W_{pre}$(전처리 과정)만큼의 추가 작업이 소요된다.
    • ClusterGCN: 추가 작업은 clustering 방법에 크게 영향을 받는다. 즉 input graph의 크기 $(n, m)$ 에 크게 영향을 받는다. (추가 작업량이 n, m에 따라 증가)
    • GraphSAINT: stochastic mini-batch selection을 통해 추가 작업이 그래프 크기에 따라 반드시 증가하지는 않는다. (추가 작업량이 n, m에 따라 반드시 증가하진 않음)

 

Depth analysis

모든 full-batch 방식의 접근은 layer의 수 $L$ 에 의존하고, 2가지 bottleneck이 존재한다.

  • $L\log{k}$ 는 layer에서 발생하는 dense nn operation(UpdateVertex : 행렬-벡터곱) → feature 작업을 위한 work로서, feature 크기 $k$만큼 소요.
  • $L\log{d}$ 는 layer에서 발생하는 sparse graph operation(Aggregate) → graph와 관련된 작업(message passing)을 위한 work로서, 전체 노드 수, 어떻게 보면 그래프에서 가장 높은 차수 $d$만큼의 작업이 소요.

mini-batch의 경우는 $\log{d}$ 대신 $\log{c}$ 가 적용된다.

→ Aggregate 연산이 full-batch처럼 전체 graph를 대상으로 하는 것이 아닌, sampling 된 $c$개의 이웃 node만을 대상으로 일어나기 때문이다.

  • ClusterGCN, GraphSAINT (graph sampling)의 경우는 $c$ 가 $d$ 로 바뀔 수 있는데, 이는 이웃의 수가 최대 $d$ 만큼이 될 수 있기 때문. (이웃 수를 정해진 수 만큼 sample 하는 것이 아니라, clustering 등의 다른 방법으로 주변 특정 노드들을 모으므로 얼마나 모일지가 모른다.)
  • 또한 사용되는 sampling/clustering 기법에 따라 추가적인 $D_{pre}$ 만큼 작업이 소요된다.
    (선택하는 전처리 알고리즘, 즉 graph partitioning 알고리즘에 따라 전처리 시간이 달라진다는 것.)

mini-batch의 경우 support vertices 또는 target vertices select를 위한 추가 작업으로 인해 전체 작업시간이 더 걸릴 수 있지만, 빠른 수렴율과 상대적으로 적은 메모리 사용량을 가진다.

(mini-batch의 경우 node/graph sampling의 추가 작업으로 인한 오버헤드로 인해 전체 작업이 full-batch에 비해 더 커질 수 있지만, full-batch에 비해 수렴이 훨씬 더 빠르고 메모리 사용량이 훨씬 더 적은편이다.)

 

 

 

Trade-off Between Parallelism & Challenge

mini-batch 에서의 parallelism 양과 mini-batch 크기에 의해 결정되는 수렴 속도에는 항상 efficiency에 대한 trade-off가 존재한다.(traditional NN에서도 마찬가지.)

  • 작은 크기의 mini-batch는 수렴 속도를 높일 수 있지만 병렬화가 힘들어지고, 큰 크기의 mini-batch는 수렴 속도가 느려질 수 있지만 병렬화가 비교적 쉬워진다.

 

GNN에서는 data sample간의 dependency 때문에 적절한 크기의 mini-batch를 결정하는 것이 매우 복잡하다.

  • 거대한 mini-batch이지만, 서로 연결이 되지 않은 node들이 있다면 정확도가 낮아질 것이다.
  • 작은 mini-batch 이지만, cluster를 형성하는 것과 같이 strongly connected node들이 많다면 정확도는 높아질 것이다.

 

 


 

 

이전 파트에 이어서 마저 작성하다 보니, 참 여러 추억(?)이 생각나기도 한다.

 

System 분야를 하나도 모르는 상태에서, 맨땅에 머리를 부딫혀가며 하나하나 차츰차츰 알아가고... 귀가하는 시간이 늦어지곤 했지만, 그래도 돌이켜보면 이전부터 관심이 조금이라도 있었던 분야를 알아가니 그 재미가 은근히 있었던 것 같다.

 

그리고 무엇보다 이쪽 연구(GNN, System)를 할때가 연구다운 연구를 했던 때 같긴 하다. 인용된 paper를 찾아가서 또 해당 부분을 읽어보고, 다른 자료(실제 code, 영상)들을 어찌저찌 찾아서 보고...

(연구비라던지, 적절한 지도 라던지는 별개이긴 했지만..^^)

 

이전 파트를 작성하고 난 후로 자잘한 가족여행도 몇번 다녀오고, 6월달에 열렸던 채용공고도 다시 한번 써보고...

작년이랑 문항이 거의 똑같긴 했었는데, 마지막 문항이 '직무 관련 경험' 에서 'AI 도구를 활용하여 성과를 낸 경험'으로 바뀌어서 상당히 당혹스러웠다ㅠ

ChatGPT, Bard가 기억상 3학기 즈음에 출시되었는데, 당시에는 인터넷으로 직접 찾는것 보다 너무 퀄리티가 떨어져서 사용을 하질 않았는데 😅...  어찌저찌 만들어서 적어내긴 헀지만 그래도 부족하긴 했나보다 ㅋㅋㅋ

 

 

여하튼,

GNN system survey paper의 리뷰(사실상 notion에 정리했던 걸 옮기는 작업)가 끝났기에,

아마..도 다음 paper 관련 포스팅은 당시에 이어서 리뷰했던 GNN system 관련 paper를 할 듯 하다.

 

 

E.O.D.

GNN 연구를 하던 시절, mini-batch 실험 이후 본격적으로 들어가기 앞서 survey paper가 있는지 찾던 중 발견한 paper.

(당시 간단한 실험을 진행했던 내용과 관련된 포스팅 링크)

 

내용이 너무 많았던 지라, 필요한 부분까지만 review 하고 틈틈히 찾았던 paper로 넘어갔던 기억이 난다.

(애초에 이 field와 관련된 paper가 기억상 21년 즈음 부터 활발했어서 그 수가 많지 않았던 기억이...)

 

이후에 LoG 컨퍼런스가 처음 열렸을 때 tutorial로 참가해서 영상을 올려주기도 하고,

이 field를 한번 조금이나마 맛 보기엔 너무나 유익했던 paper 였기에,

review 했던 부분 까지만이라도 포스팅으로 남겨두고자 한다.


Paper link

(지금 보니 24년에 IEEE journal에 투고되었기도 하다. link는 review를 진행했던 arXiv.)

 

Tutorial video link (LoG 2022)

 

 

 

Introduction

GNN은 여러 field에서 활용되고 있고, 실 세계의 다양한 문제들을 풀어나가고 있다.

 

대표적인 예시로 social science, bioinformatics, chemistry, medicine, cybersecurity, entertainment services, transportation 등 이 있다.

(사실상 data가 graph로 표현될 수 있는 field라면 얼마든지 활용이 가능한게 아닌가...싶은 생각이 들기도 한다.)

 

GNN의 특이한 점은, 전통적인 딥러닝(traditional deep learning)과 그래프 처리(graph processing)가 함께 섞인 형태라는 것이다.

  • 우리가 흔히 접하는 일반적인 data(이미지와 같은 grid 형태)엔 잘 동작하지 못하며,
  • data 자체가 매우 복잡하고 불규칙적인 형태이며, 계산의 결과가 data-driven이다.
    (data 그 자체의 특성에 따라 결과가 나온다? 정도로 생각하면 될 듯 하다.)

또한 node와 edge가 복잡한 data와 이를 processing하는데 매우 긴밀하게 연관이 되어 있는데,

대다수 GNN의 연산은 각 node $i$는 $k$차원의 feature vector에 assign 되고, 이 feature vector는 node $i$의 이웃 node들의 vector와 또 결합되는 과정이 반복된다.

(간단히 말해 node마다 feature vector가 있고, 이 feature vector가 이웃 node들의 feature와 aggregate하여 feature learnig을 한다는 것.)

 

어떻게 보면 계산 과정이 PageRank의 label propagation algorithm과 거의 유시하지만, feature가 추가되어 계산 과정이 더욱 복잡해진다.

 

하지만 앞서 설명한 예시는 가장 간단한 GCN의 예시이고, 연산 과정이 더욱 복잡한 GNN들이 대다수 존재한다.

 

고 차원의 data가 모든 edge에 포함되어 있을 수 있고, 매 iteration 마다 복잡한 update를 통해 edge data가 갱신된다.

  • 대표적인 예시로, GAT의 경우 하나의 edge $(i,j)$의 가중치(weight)를 계산하기 위해 두 node의 feature vector를 concat한 후, trainable한 weight vector와 dot product를 수행한다.

이처럼 계산 과정이 복잡해짐에 따라, 병렬(parallel) 및 분산(distributed) 처리가 계산 효율성을 위해 필적인 요소가 되었다.

 

현대 컴퓨터 구조는 대부분 병렬 구조로서, core가 socket을 구성하고, socket은 NUMA(Non-Uniform Memory Access) compution node(blade, chassis, rack 등... 서버실에 있는 디스크로 생각하면 될 듯)를 구성한다.

 

거대한 memory bank를 통해 data의 분산 저장이 가능해지고, 이 구조들은 전부 병렬적으로 작업을 수행할 수 있다.

  • 마찬가지로 단일 core 또한 vectorization, pipelining, instruction-level parallelism(ILP)를 제공하고 있다.

이러한 구조들은 대부분 heterogeneous(이질적. 서로 다른 구조)하며, processing unit이 CPU/GPU/FPGA 들 중 하나이다.

 

GNN workload에서 더 좋은 성능을 얻기 위해 이런 풍부한 자원들을 제대로 활용할 수 있는 방법들엔 무엇이 있을까?

 

본 논문에서는 이 질문에 대한 답으로,

  • GNN들의 다른 관점을 분석하며, 그 중에서도 parallelism과 distribution에 초점을 맞춘다.
  • work-depth model과 같은 기본적인 이론적 병렬 컴퓨팅 매커니즘을 사용해 구조들의 insight를 기술하고자 한다.
    (work-depth model에 대한 설명은 https://en.wikipedia.org/wiki/Analysis_of_parallel_algorithms 참고. 간단히 말해 computation이 얼마나 병렬화가 가능(parallelisable)한지 이해하는 접근 방식이라고 한다.)
  • GNN에서 사용되는 선형 대수 공식(model의 수식)에 초점을 맞추고, 관련된 tensor의 sparsity & density를 조사하고자 한다.
    $\rightarrow$ GNN computation 성능에 대한 추가적인 정보를 제공받을 수 있고, vectorization과 같은 병렬화 매커니즘을 쉽게 적용할 수 있도록 하는 길을 안내해줌으로써 더 효율적인 GNN computation을 개발 할 수도 있을 것이다.
  • GNN 병렬처리에 대한 심층적인 분류체계를 제공, 즉 GNN의 기본적인 병렬처리의 종류들을 구분할 것이다.
    (일부는 traditional deep learning에서의 방법과 거의 동일하지만, 일부는 GNN에 특화되어 있기 때문.)
  • GNN은 graph embedding 영역에도 속한다고 볼 수 있는데(embedding 구축을 위한 model), 본 논문에서는 random walk, graph kernel design과 같은 GNN-base가 아닌 방법들은 전부 제외한다.

 

 

Graph Neural Networks: Overview

주로 사용되는 symbol table

GNN Computation: High Level Summary

일반적인 GNN 연산과정

 

input은 graph dataset으로, single graph(1개의 large graph, 대표적으로 Reddit과 같은 social graph) 또는 여러개의 graph(크기가 작은 여러개의 graph, 대표적으로 PPI와 같은 화학분자구조 graph)가 될 수 있다.

 

input에선 마찬가지로 주어진 task에 대한 semantic 정보가 인코딩 된 input feature vector가 함께 구성된다.

 

즉, (대부분/일반적으로) input은 graph data + feature vector가 들어오는 셈이다.

 

간단한 예시로, citation network를 생각해보자.

 

여기서 node는 paper를 의미하고, edge는 paper간 인용(citation)관계를 나타내게 된다.

  • 각 node마다 input feature vector가 따라올 것이고, 이는 주어진 paper를 요약한 one-hot bag-of-words encoding.
  • 이후 GNN model은 graph의 구조와 input feature vector를 사용해 output feature vector를 생성한다.
  • input-output의 중간 과정에서 보통 hidden latent vector(잠재 벡터)가 생성되고, 이는 최소 1번 이상 갱신되는 값.
    (즉 학습하게 되는 vector/embedding)
  • 결과로 나온 output feature vector를 이용해 downstream task(이 경우 대부분 node classification)를 수행한다.

단일 GNN layer의 구조

 

단일 GNN layer의 구조는 위 그림처럼 표현할 수 있으며, 연산 과정을 정리하면 다음과 같다.

  • graph-related operation을 수행. 즉 message passing & aggregation을 수행.
    (GCN의 예시로 node $v$의 모든 이웃의 feature vector를 aggregate하여 자기 자신의 feature vector와 summation.)
  • 이후엔 전통적인 neural network operation을 수행.
    (MLP 또는 linear projection)
  • 마지막으로는 linear activation 또는 normalization을 수행.
    (GCN의 경우 ReLU activation)

 

그렇다면 GNN이 일반적인 NN(Neural Network)과 다른 점이 무엇일까?

 

input으로 들어온 data sample에 dependency가 존재할 수 있고, 이러한 특성 때문에 GNN의 병렬화가 더욱 어려워진다.

GNN의 input으로 들어오는 data sample의 종류

 

위 그림과 같이, 하나의 sample은 node일 수도 있고, edge일 수도 있고, 작은 subgraph일 수도 있고, graph 그 자체가 될 수도 있다.

 

기본적으로 node와 edge는 서로 inter-dependency(상호의존성)가 존재한다.

 

즉, node들은 edge를 통해 연결되어 있고, edge는 몇몇 개의 node를 공유하고 있다.

(어찌 보면 당연한 이야기 긴 하지만... survey paper이다 보니 상세하게 알려주는 느낌)

 

data sample로 사용되는 graph들은 보통 independent한 경우가 대부분이고, 대표적인 task 예시로는 화학분자구조 의 분류(classification)가 있다.

  • 이러한 특징(independent graph as data sample)은 image와 같은 traditional deep learning에 활용되는 data sample과 유사하며, sample(단일 image)들은 서로 간 명시적인 의존성(dependency)가 없다.
  • 하지만 image와는 다르게 이러한 graph들은 단일 graph마다 크기가 다를 수 있으며, 여기서 load balancing issue가 생길 수 있다.
    (마치 data sample이 video인데, 이 video들의 길이가 서로 다른 것 처럼)

 

 

Input Datasets & Output Structures in GNNs

상단 TABLE 1 참조.

 

 

GNN Mathematical Models

GNN model은 adjacency matrix $A$와 input feature matrix $X$를 받아서 output feature matrix $Y$를 생성하는 수학적 변환을 정의한다.

 

즉, $AX \approx Y$를 정의하는 셈.

 

2개의 matrix $A$와 $X$를 기반으로 $Y$를 구성하는 방법은 활발한 연구분야(matrix approximation 또는 low-rank approximation)이며, 이를 토대로 아래 그림과 같이 다양한 GNN들이 제안되어 왔다.

categories of GNN models

 

병렬 및 분산 처리에서 중요한 것은 2가지로, LC 또는 GL을 통해 대부분의 GNN 모델은 공식화 할 수 있다는 점이다.
(GNN model을 아래의 2가지 범주의 수식으로 표현할 수 있다는 의미)

 

Local(LC) GNN Formulations

단일 node(edge)에서 동작하는 함수를 기반으로 하는 공식화이다.

(single node(edge)-level에서 동작하는 함수를 통해 model을 구성)


즉, 이 경우엔 vector - vector (또는 dense matrix - dense vector) 단위로 for loop을 통해 계산한다.

  • 주어진 node $i$에 대한 latent feature vector $\mathbf{h}_i$는 해당 node의 이웃 집합의 feature vector들에 대해 permutation invariant aggregator function $\oplus$ (대표적으로 sum, max)를 적용해 구할 수 있다.
    • 또한 node $i$의 각 이웃 node의 feature vector는 추가적으로 함수 $\psi$를 통해 변환될 수 있고, $\oplus$를 거쳐서 나온 결과는 또 다시 $\phi$ 함수를 통해 변환될 수 있다.
  • 이 일련의 과정이 하나의 GNN layer를 구성하게 되며, 이를 기반으로 한 GNN 모델을 local(LC)로 명명하며, 위의 과정을 식으로 나타내면 다음과 같다.  
    node i에서 다음 layer의 feature vector를 계산하는 식.
    • 함수 $\psi$에 따라 GNN 유형을 3개로 분류가 가능하며, 이는 Conv GNN(C-GNNs), Attentional GNN(A-GNNs), Message-Passing GNN(MP-GNNs)이다.
    • 이 경우 함수 $\phi$는 보통 fixed scalar, scalar를 반환하는 learnable function, vector를 반환하는 learnable function이 된다.
    • GCN을 예시로 생각해보자.
      $\oplus$는 자신과 모든 이웃 node를 aggregate 하는 function이 되고,
      $\psi$는 각 이웃의 feature vector마다 곱해주는 scalar 값($1/\sqrt{d_id_j}$)이 되며,
      $\phi$는 trainable parameter matrix $W$와 함께 ReLU를 취하는 linear projection이 되며,
      따라서 GCN을 LC 형태로 나타내면 다음처럼 표현할 수 있다.
      GCN의 propagation rule의 vector representation
      (GCN paper에서는 matrix 형태로 기술하지만, 여러 강의자료나 paper를 보면 이처럼 vector 형태로 기술하기도 한다.)

 

Global(GL) GNN Formulations

모든 node(edge)와 관련된 vector를 그룹화 하여 matrix 연산에 기반한 방법이다.
(global node(edge)-level에서 vector를 쌓은 matrix로 matrix 연산을 통해 model을 구성)

 

즉, 이 경우엔 vector - matrix 또는 matrix - matrix 단위로 MM(Matrix Multiplication)을 통해 계산하며,
직전의 LC를 좀 더 일반화 한 셈으로 볼 수 있다.

  • 많은 GNN model은 또한 matrix $\mathbf{X}$, $\mathbf{X}$, $\mathbf{X}$ 들의 matrix 연산 형태로 표현할 수도 있고, 이 형태를 기반으로 한 GNN model을 global(GL) 으로 명명하고자 한다.
    • GCN을 예시로 생각해보자. 앞선 LC 형태의 수식을 matrix 형태로 표현하면 다음과 같다.
      GCN propagation rule의 matrix representation
      이때 $\hat{A}$는 self-loop이 포함된 adjacency matrix가 normalized 된 형태로, $\hat{A} = \tilde{D}^{-1/2}\tilde{A}\tilde{D}^{-1/2}$ 이며, 이 normalization은 LC 형태에서의 scalar 값 $1/\sqrt{d_id_j}$를 내포하고 있다. 
      (GCN formula와 관련된 상세 내역은 해당 포스팅(링크) 참고.)
  • 대부분의 GL 형태의 model은 adjacency matrix $A$의 더 높은 거듭제곱을 사용하는데, 이는 한 node를 기준으로 더 떨어진 hop 정보를 얻기 위함이다.
    (graph theory 에서 나오는 정의 로 알고있지만... 상세한 내용은 graph theory를 제대로 공부하지 않아 그렇다 라는 정의 정도로만 알고 있다.)
    • 이에 따라 $A$를 1번만 사용한 linear model이 될 수도 있고, 여러번 사용한 polynomial model이 될 수도 있고, rational power를 곱한(분수 제곱형태) rational model이 될 수도 있다.
    • 또한 연산에 있어 sparse matrix, dense matrix가 모두 사용되며, 이런 matrix에 대한 작업의 성능 패턴이 크게 다르기 때문에 parallelization routine에 대한 가능성이 존재하는 것이 특징이다.

 

 

GNN Inference vs. GNN Training

해당 부분은 일반적인 NN에 대한 내용과 거의 동일하기에 기술하지 않음.

 

 

GNN Programming Models and Operators

최근(2022년) 연구들을 통해 시스템 관련 커뮤니티에서 programming model & execution model을 제공하고 있다.

(즉 PyG, DGL 같은 framework 이야기)

더보기

programming model은 특정 코드 패턴에 연결된 실행 모델로, Spark를 생각해보면 된다. Java가 기본 언어이고, Spark가 프로그래밍 모델인 셈.

 

execution model은 언어 요소의 동작을 지정하는 모델로, 이를 적용하면 해당 프로그래밍 언어로 작성된 프로그램의 동작을 생성할 수 있다. 즉 Spark 플랫폼이 특정 어플리케이션을 처리하는 방식을 생각해보면 된다.

 

이런 model들은 아래 그림과 같이 LC formulation, GL formulation 형태로 GNN의 주요 function을 구현할 수 있도록 도움을 준다:

GNN model formulation과 어떻게 이를 GNN operator로 변환하는지에 관한 그림. 즉 framework의 동작 과정으로 볼 수 있다.

 

 

가장 널리 쓰이는 programming model은 SAGA(Scatter-ApplyEdge-Gather-ApplyVertex) 이며, LC formuation으로 보면 다음과 같다:

 

  • Scatter를 통해 feature vector를 concat, ApplyEdge(UpdateEdge)를 통해 변환.
    $\rightarrow$ 즉, 함수 $\psi$를 정의하는 동작이고, target node와 인접한 1개 node간의 message passing을 수행한다.
  • Gather를 통해 앞선 작업(Scatter & ApplyEdge)의 출력을 aggregate.
    $\rightarrow$ 즉, 함수 $\oplus$를 정의하는 동작이고, target node와 (선택된) 인접한 모든 node간의 message를 AGGREGATE한다.
  • ApplyVertex를 통해 aggregated vector에 특정 연산을 적용.
    $\rightarrow$ 즉, 함수 $\phi$를 정의하는 동작이고, target node의 새 feature를 target node의 이전 feature와 AGGREGATE한 feature를 이용해 update한다.

(기억상 PyG docs에서 이 SAGA와 관련된 그림이 그려진 example을 봤던 기억이 있는데... 몇년 새에 업데이트 되어서 그런지 보이지가 않는다 😥)

 

그럼 왜 이렇게 programming model을 정의할까? 

 

당연히 programming 적인 이점도 있지만, 이러한 연산 하나하나를 병렬화 하여 acceleration을 할 수 있기 때문이다.

(자세한 내용은 논문 Section 4 - Model Parallelism을 참고.)

 

 

Taxonomy of Parallelism in GNNs

일반적으로 traditional DL에서의 병렬화 방법은 2가지가 존재한다: data parallelism, model parallelism.

 

Data Parallelism서로 다른 worker로 data sample이나 weight를 분할&전달하여 training하는 것이고,

Model Parallelism서로 다른 NN layer가 병렬적으로 실행되거나(pipeline parallelism), 단일 operator가 병렬적으로 실행되는 것(operator parallelism)이다.

 

GNN에서의 parallelism 또한 동일하게 2가지로 분류될 수 있는데, 앞서 언급한 traditional DL과 명확한 차이점이 존재한다.

Overview of GNN parallelism

 

Data Parallelism은 크게 2가지로 분류된다:

  1. Mini-batch parallelism: mini-batch execution을 병렬화하여, 각 execution 후에 weight update.
    • dependent mini-batch parallelism은 sample 간 서로 dependency가 있는 경우
    • independent mini-batch parallelism은 sample 간 서로 dependency가 없는 경우로, 기존 traditional DL에서의 data parallelism과 거의 유사.
  2. Graph [partition] parallelism: 한 worker에 batch를 담을수가 없는 경우, batch 자체를 병렬화 하여 전체 batch execution 후에 weight update
    • 말 그대로 graph를 partition하는 parallelism으로, 단일 mini-batch가 너무 거대한 경우에도 적용이 가능.

 

Model Parallelism은 크게 3가지로 분류된다:

  1. Pipeline parallelism: 실제 GNN layer 자체를 pipelining(macro-pipeline)하거나, 단일 GNN layer에서의 sample processing 과정을 pipelining(micro-pipeline).
  2. operator parallelism: 단일 feature vector의 update를 병렬적으로 수행(feature parallelism)하거나, 서로 다른 neighbor를 다른 worker에 할당하여 병렬적으로 갱신(graph [structure] parallelism).
  3. ANN-parallelism: UpdataEdge & UpdateVertex 이후의 dense NN operation에 기존의 traditional한 NN parallelism을 적용.

 

뭐.. 단순히 보면 기존 DL의 parallelism과 (아마도) 거의 동일하지만,

단지 graph data임에 따라 dependency가 생기므로, 이를 고려한 기법이 상세화 되는 것으로 볼 수 있다.

 

 

Parallel and Distributed Models and Algorithms

본 논문에서 어떤 기준으로 parallel/distributed model/algorithm을 평가할 것인지를 기술한다.

 

single-machine (with shared memory)에선 work-depth (WD) analysis를 사용하도록 하고, 이는 병렬 알고리즘의 bounding runtime을 분석하는데 있어 쳬계가 잡힌 접근 방식.

(work-depth analysis에 관한 설명은 링크 참조)

single-machine에서의 목적은 work(총 연산 횟수)가 너무 증가하는 것을 방지하면서, depth(알고리즘에서의 가장 긴 실행과정)를 최소화 하는 것.

 

multi-machine (with distributed memory)에선 알고리즘의 3가지 비용을 생각하도록 한다:

$\rightarrow$ 총 communication의 양, 총 synchronization의 양, 총 computation의 양.

 

이 3가지를 최소화 하는 것이 목적 multi-machine에서의 목적이고, 자주 사용되는 접근 방식은 Bulk Synchronous Parallel(BSP)이다.

(BSP에 관한 설명은 링크1 , 링크2 참조)

 

 

 

Section 3 - Data Parallelism 파트는 Parallel and Distributed Graph Neural Networks: An In-Depth Concurrency Analysis (2)에서 이어서 기재.

 

 

 


 

Distributed GNN 연구 프로젝트를 시작하기 전에 가장 먼저 읽었던 paper이기도 하고, Distributed System에 큰 흥미를 불러다 준 계기가 된 paper 이기도 하다.

 

원래대로라면 순서 상 기존 DL에서의 Distributed training 같은 내용을 먼저 정리하고 난 후에 이를 작성해야 하는데,

글을 작성하던 당시도 그렇고, 내가 순전히 학습했던 순서대로 작성을 하는게 나을 것 같다... 하여 이를 먼저 작성했다.

 

기억상 2월 말? 3월 초 정도에 이 포스팅을 작성 중이었는데, 한창 작성하고 있을 때 상반기 시즌이 시작되고... 

 

상반기 시즌이 지나고 4월 말 ~ 5월 초 즈음에 가족 행사, 일본에서 일하는 친구가 골든위크 겸 내한해서 친구들과도 만나고...

 

상반기 시즌도 정말 정신없이 지나갔는데, 지나고 난 후 약 한달되는 기간도 여러 일정을 보내다 보니 벌써 이때가 되었다 😦 

시간이 참 빠르게 지나가긴 한다.

 

여하튼, Data Parallelism 부분은 다음 포스팅에 이어서 작성하려고 한다.

 

애초에 Data Parallelism까지만 제대로 review하기도 했고, 해당 section의 분량도 꽤 많기 때문에...

 

 

E.O.D.

 

 

Preliminaries

NeighborLoader 포스팅

 

지난번 포스팅에서 PyG의 mini-batch training을 위한 방법 중 하나인 NeighborLoader를 간략하게 살펴보았다.

 

이번엔 NeighborLoader와 간단한 dataset을 활용하여

이 neighbor sampling (또는 node-wise sampling)의 특징(?)을 알기 위해 간단하게 진행했던 실험에 대해 정리하고자 한다.

 

작성 편의상 sampling을 수행하는 기준 node, 즉 sampling을 수행하였을 때 최 상단에 위치하게 되는(기준이 되는) node를 anchor node로 작성하였다.

 

 

 

Cora dataset & EDA

여러 초장기 GNN paper에 자주 등장한 dataset이다.

 

PyG에선 torch_geometric.datasets.Planetoid 에 함께 포함되어 있다.(공식 doc 링크)

 

여러 GNN paper에 기재된 듯이, 비교적 작은 규모의 citation network 이다.

(전체 node의 수는 2708, edge 수는 5429, feature vector의 차원이 1433.)

description (from papers with code)

 

그럼 그래프가 어떻게 생겼을까?

 

살펴보면 다음과 같다. (이미지 출처는 이미지에 포함)

class 별로 coloring 된 cora dataset.

 

직접 plotting해본 것도 있지만... 아무래도 이렇게 이쁘게 그려주신 분이 있다면 :)

 

추가적인 EDA를 위해 필요한 라이브러리를 import 한다.

import torch

import networkx as nx
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import pandas as pd

from torch_geometric.datasets import Planetoid
from torch_geometric.loader import NeighborLoader
from torch_geometric.seed import seed_everything
from torch_geometric.utils import to_networkx, unbatch_edge_index

seed_everything(62)

dataset = Planetoid(root='dataset', name='cora')

data = dataset[0]
del dataset

data.n_id = torch.arange(data.num_nodes)

 

각 node마다의 degree 정도/분포도를 확인.

graph = to_networkx(data)
degree_list = list(graph.degree)
df = pd.DataFrame(degree_list, columns=['n_id', 'degree'])
print(df['degree'].describe())

degree 분포

이미지로 봤던 graph에서 처럼, degree 분포가 상당히 극단적이다.

(근데 사실 대부분의 graph dataset들은 이런 식의 long-tail distribution인 경우가 많다.)

 

추가적으로 train mask, val mask, test mask 라는 것이 존재한다.

 

이는 각 train/val/test 마다 masking을 한 것으로, T/F로 이뤄진 값이며,

node를 unseen node처럼 간주하기 위해 사용하는 셈 이다.

 

print(sum(data.train_mask))    # 140
print(sum(data.val_mask))    # 500
print(sum(data.test_mask))    # 1000

 

train에는 140개의 mask가, val에는 500개의 mask가, test에는 1000개의 mask가 있다.

 

이게 도대체 무슨 의미가 있고, 왜 있는 걸까?

 

앞서 언급하였듯, Cora dataset은 데이터의 규모가 상당히 작은 편이다.

 

2708 node에 대해, mask를 적용하면 그 값이 False인 node를 train에서 제외하는 셈이다.

 

해당 갯수(True인 갯수)의 노드만을 가지고 train/val/test를 실시한다는 의미로 볼 수 있다.

(적은 양의 data로 model의 충분한 generalizaion을 돕기 위해서 사용하는 셈 이라고도 볼 수 있을 듯.)

masking의 예시

 

 

Mini-batch testing

GraphSAGE의 sampler가 어떻게 mini-batch를 생성하는지 직접 코드를 통해 확인해보자.

NUM_NEIGHBORS = [2,4]    # 2-hop sampling
# NUM_NEIGHBORS = [-1]    # 1-hop sampling
BATCH_SIZE = 16
INDEX_NUM = 0

loader = NeighborLoader(
    data = data,
    num_neighbors = NUM_NEIGHBORS,
    batch_size = BATCH_SIZE,
    input_nodes = data.train_mask, # "len(sum(data.train_mask)):140 / batch_size" 갯수 만큼의 batch가 만들어진다.
    # directed=False, # RuntimeError: Undirected subgraphs not yet supported
    disjoint=True # each seed node will create its own disjoint subgraph : 각 anchor node마다 disjoint한 sub-graph를 생성. 
)

subgraph_list = []
nodes_in_subgraph = []
edges_in_subgraph = []
for batch in loader:
    subgraph_list.append(batch)
    # 해당 배치에서 anchor node 를 제외하고 새로 sampling된 node
    nodes_in_subgraph.append(len(batch.n_id.tolist()) - BATCH_SIZE)
    # 새로 sampling된 노드들과 anchor node들 간의 connectivity
    edges_in_subgraph.append(batch.edge_index.numpy()[1].shape[0])

print('Total # of batches : ', len(subgraph_list))    # 9

 

loader에 대한 loop을 실행할 때 실질적인 sampling이 수행된다.

 

여기서, disjoint=True 를 하면 서로 연결된 anchor node끼리는 computation graph에 포함시키지 않는다.

 

즉, anchor node끼리 겹치지 않으며 anchor node 1개당 고유한 computation graph를 생성하게 되고,

약간의 작업을 통해 batch안에 있는 computation graph들을 각각 분할시킬 수 있다.

(당시 공식 repo discussion 탭에서 질문했던 내용: https://github.com/pyg-team/pytorch_geometric/discussions/6325)

 

그럼 batch 안에 들어가는 실제 computation graph는 어떻게 생성되는지 확인해보자.

 

sample_batch = subgraph_list[INDEX_NUM]
# edge_batch = sample_graph[sample_graph.edge_index[0]]
# print(sample_graph.edge_index[0]) # source->target 에서 target에 해당하는 index만을 챙기기.
### batch vector에서 실제로 어떤 node가 어떤 sub-graph에 할당되어 있는지 확인. 
### 즉, 기존 edge_index랑 이 값이랑 비교하면 어떤 앵커가 몇개를 샘플링했는지 확인가능.
# print(sample_batch.edge_index.numpy())
# print(sample_batch.batch[sample_batch.edge_index[0]].tolist())

# batch안에 있는 개별 anchor node마다의 computation graph를 추출할 수 있음.
sample_graph_edge_index = sample_batch.batch[sample_batch.edge_index[0]]
for i in range(BATCH_SIZE):
    edge_index_for_i = sample_batch.edge_index[:, sample_graph_edge_index == i]
    print(edge_index_for_i.numpy())

 

print된 결과물(첫번째 batch에 포함된 computation graph들)을 보면 다음과 같다.

현재 batch에서의 생성된 computation graph

 

모든 node마다 2-hop sampling을 수행하였고, 1-hop에서는 2개의 node를, 2-hop에서는 4개의 node를 sampling 했다.

 

앞서 수행했던 data.n_id = ~~ 부분을 통해 edge_index에 있는 값 (0~15)과 실제 graph에서의 id값인 n_id의 매칭을 통해 각 배치마다 어떤 node가 computation graph를 어떻게 형성하는지 확인 가능하다.

 

앞서 지정한 BATCH_SIZE 개수 만큼의 computation graph가 생성된 것을 확인할 수 있는데,

눈여겨 볼 점은 각 computation graph마다의 크기가 다른 점이다.

 

상단 Cora dataset의 graph plot을 봐도 알 수 있듯, 각 node의 degree가 long-tail distribution의 형태를 따르고 있기에

sampling을 수행할 때 고립된(isolated) node가 있다면 서로간의 sampling만을 수행하고 종료되는 것을 짐작할 수 있다.

 

그렇다면 무엇이 문제일까?

 

비교분석을 위해 간단한 코드를 작성해서 chart로 확인을 해보자.

# ## x축은 각 batch id, y축은 그 길이 값 -> bar chart
graph_info_tuples = list(zip(nodes_in_subgraph, edges_in_subgraph))
df = pd.DataFrame(graph_info_tuples, columns=['node_num', 'edge_num'])

ax = df.plot(kind='bar', rot=0, xlabel='batch_id', ylabel='value', title=f'batch_size={BATCH_SIZE} \n num_neighbors={NUM_NEIGHBORS}', figsize=(12, 8))#, cmap=cmap)
df.plot(kind='line', xlabel='batch_id', ylabel='value', ax=ax)#, cmap=cmap)
for c in ax.containers:
    ax.bar_label(c, fmt='%.0f', label_type='edge')
ax.margins(y=0.1)
ax.legend(title='columns', bbox_to_anchor=(1, 1.02), loc='upper left')
plt.show()

 

먼저 batch_size를 다르게 (batch마다 들어가는 anchor node 수를 다르게) 한 경우를 살펴보면 다음과 같다.

 

batch마다 들어가는 anchor node 수를 다르게 한 경우, 한 개 batch마다의 전체 computation graph들의 크기가 증가하는 경향을 볼 수 있다.

 

즉, batch_size크게 잡으면(한 batch에 넣을 anchor node수를 늘리면) 1개 batch당 computation graph 수 증가하게 되고, batch당 계산량의 차이가 더 심해질 수 있다.

 

 

다음은 num_neighbors를 다르게 (고려하는 hop을 다르게, 고려하는 이웃 수를 다르게) 한 경우는 다음과 같다.

 

고려하는 hop 수를 늘리거나, 고려하는 이웃의 수를 늘리는 경우 (앞서 살펴본 경우와 비슷하게) 한 개 batch마다의 전체 computation graph의 깊이/크기 차가 심하게 증가하는 경향을 확인할 수 있다.

 

batch당 computation graph의 깊이(depth)/크기가 증가하는 것을 확인할 수 있고, 그 차이의 폭(gap)이 더욱 커지는 것을 바로 확인할 수 있다.

 

특히 위 사진의 3사분면과 4사분면에서 그 차이가 가장 크게 두드러지는 것을 확인할 수 있는데,

고려하는 이웃의 수가 많으며 고려하는 hop 수가 늘어남에 따라 computation graph의 깊이/크기가 지수적으로 폭발하는 현상neighborhood explosion이라고 한다.

(여러 paper에서 언급되는 용어 이기도 하고, PyG 공식 docs에서도 간략하게 소개하고 있다.)

 

 

 

Consideration

neighborhood sampling은 random sampling을 통해 정말 간단하면서도 상당히 안정적인 mini-batch training을 가능하게 한다.

 

하지만 앞서 진행한 간단한 mini-batch test를 통해 확인한 것 처럼, 무턱대고 sampling을 수행하게 되면 batch마다의 computation graph 크기가 달라지게 되고, neighborhood explosion 문제가 발생할 수 있다.

 

그렇다면 이게 왜 문제가 될까?

 

실제 산업현장이 아닌 이상, 대부분 single GPU로 시간을 들여서 이런 문제는 충분히 커버할 수 있는 수준일 것이다.

(위처럼 Cora 같은 dataset이나, Reddit 같은 dataset이라면...)

 

하지만 실제 산업현장(실세계, real world)에서 등장하는 대부분의 데이터들은 규모가 정말 방대한 경우가 많고,

single GPU로는 턱 없이 부족한 경우가 많다.

(당장 Jure 교수님 산하의 stanford 팀에서 개발/운영중인 OGB(Open Graph Benchmark)를 봐도 large-scale challenge가 있고, 제공중인 dataset에도 상당히 큰 규모의 dataset이 있다.)

 

결국 Multi-GPU를 통한 distributed training이 필요한데, 보다시피 graph data의 특성 상 이게 상당히 힘들다.

(즉 large graph로부터 mini-batch를 어떻게 잘 만들 것 인지가 문제.)

 

GPU마다의 load balance를 맞추기 위해선 각 GPU마다 담당하는 양, 계산량이 비슷해야 synchronize가 잘 되어서 이상적인 distributed training이 될 것인데...

 

앞서 보았듯, mini-batch 마다 그 안에 들어있는 graph data의 크기가 제각각이니 synchronization도 잘 이뤄지지 않게 되고, GPU마다 계산량이 달라지게 되며 결국 놀게되는 GPU가 생겨날 수 밖에 없다.

(이렇게 놀게되는 GPU가 생겨서 작업 시간이 비효율적?이게 되는 문제straggler problem이라고도 한다.)

 

결국 mini-batch를 어떻게 잘 만들어 볼 것이냐 가 관건일 것인데, 단순히 GraphSAGE에서 제안한 random sampling 만으로는 mini-batch를 어떻게 적절하게 잘 만들기가 상당히 골치아프다는 점을 짚고 넘어갈 수 있다.

 

 

 

Conclusion

물론 다양한 paper들이 large-scale graph를 어떻게 효율적으로 distributed training 할 수 있는지 그 방법을 제안하기도 했고, Tiktok의 개발사?로도 알려진 ByteDance에서도 관련된 paper를 내기도 했다.

(당시 review했던 paper들은 기회가 된다면 천천히 posting 하는 것으로...)

당시 GNN 공부와 distributed training을 학습하며 정리했던 notion 페이지 일부

 

글을 작성하며 예전 notion에 정리했던 내용들을 천천히 다시 둘러보니... 참 여러 생각이 든다.

 

돈 한푼 없이 정말 말 그대로 재미?로 시작해서, 다른 연구실 분과 협업도 해보고, 실험을 하면서 이런 현상이/문제가 정말로 있구나 하는걸 직접 확인하고, (비록 국내 학술대회 였지만) 첫 논문도 작성해보고...

 

단지 프로젝트가 상당히 길어질 것 같아 3학기를 마친 후 방학때 물러나게 되었지만, 기회가 된다면 다시 한번 진득하게 보고 싶은 field 이기도 하다.

 

지금은 뭐... 연구실의 다른 후배 분이 이어서 해주시고 있는지, 프로젝트가 그냥 무산났을지도 모르겠다.

당시에도 연구실에서 이 프로젝트를 하던 인원이 나 밖에 없었고, 4학기때 새로 들어온 후배 분에게 간략?한 인수인계를 해드리긴 했는데... 어떻게 진행중인지는 ^^;;

 

 

이전 PyG 포스팅 이후 딱 하반기 시즌이 열리는 바람에 하반기에 참 치이고 데이고,

 

정신없이 지내다가 한숨 돌리고 다시 기록해둬야지 하고 보니 어느새 거진 반년이 지나버리긴 했지만..

마음 속 응어리가 조금이나마 줄어든 기분은 든다. :)

 

다음 번 이쪽(Programming) 포스팅이 아...마 있을지는 잘 모르겠지만, 포스팅을 하게 된다면 당시 비교실험 등 을 진행했던 코드를 작성하며 review 해보고자 한다.

(집의 환경이 multi-GPU가 아니기에, 아마 single-GPU 코드를 작성하게 될 것 같긴 하다.)

 

 

E.O.D.

'학업 이야기 > Programming' 카테고리의 다른 글

PyTorch Geometric(PyG) - NeighborLoader  (5) 2024.08.26
PyTorch Geometric(PyG) 개요  (0) 2024.08.05

18년 전역 당시, 데이터 사이언스 공부를 혼자 시작해보며 설치했던 anaconda 와 여러 패키지들.

 

연구실에 다니던 시절, 아직 원격 접속을 세팅하지 않았을 때,

집에서라도 조금씩 해둘걸 해두자 라는 마음에 연구실과 비슷한 환경으로 다시 설치를 하고자 했었다.

 

하지만 연구실에서 사용하던 데스크탑과 (현재까지도 사용 중인) 집 데스크탑의 HW 차이는 조..금 많이 심했다.

 

연구실에선 아마 기억상 3060ti?를 사용중이었는데, 집 데스크탑은 1060 3GB...

 

당시엔 그래서 환경을 따로 만들어 pytorch_cpu를 설치해서 하다가 도저히 참을수가 없어서 빠르게 원격 세팅을 마쳤던 기억이 난다🤣

 

이미 졸업을 하기도 했고, colab은 뭔가 불편했던 기억이 많이 남아있기에

그냥 마음편히 집의 데스크탑을 조금 더 굴려보기로 결정했다.

 

 

현재 집 데스크탑의 구성은 다음과 같다:

  • CPU: Intel(R) Core(TM) i5-4670 CPU @ 3.40GHz
  • RAM: 16.0GB DDR3
  • GPU: NVIDIA GeForce GTX 1060 3GB

그렇다. 상당히 오래됐다...

 

기억상 고3 졸업 or 새내기 시절에 작은형이 블레이드&소울을 한다고 구매하고 쓰던걸 넘겨받고 계속 쓰는 중이다.

 

10년은 진즉에 넘었지 싶다.

친구들도 컴퓨터 좀 그만 괴롭히고 놔주라고 하는데, 백수가 돈이 어디있겠는가 ㅎㅎ

 

 

그래서 우선 설치되어있던 CUDA, Anaconda를 삭제했다.

 

설치되어 있던 CUDA 10.1 관련 프로그램을 전부 삭제하고...

 

 

설치되어있던 Anaconda를 삭제했다.

 

근데 문제아닌(?) 문제 가 생겼다.

Anaconda 삭제가 도저히 끝나질 않았다 ㅋㅋㅋ

 

기다리고 기다려보니 거의 1시간 ~ 1시간 10분 정도 걸린 듯 하다.

기다리는 동안 친구들과 수다

 

18년 당시 Python을 처음 접해보며 시작했을 땐 가상환경이라는 것도 잘 몰랐고, 전부 base에 설치해서 했던지라

진짜 온갖 패키지가 다 있어서 삭제에 시간이 많이 걸린게 아닌가 싶긴 하다.

(졸업 프로젝트때 설치한 Django, Flask 같은 웹 관련 패키지, 공부할때 설치한 pytorch, tensorflow, keras, xgboost 같은 ML, DL 관련 패키지, plotly 같은 시각화 패키지 등...)

 

그렇게 온전한 삭제를 마치고, pytorch와 pyg를 설치하기 위해 우선 CUDA부터 설치하기로 했다.

 

windows에서 설치를 했던게 아..마 19년에 설치했던 것으로 기억하는데, 현재 사용중인 GTX 1060이 호환이 될까 싶어 인터넷 검색을 하던 중 마침 (비교적 최근에 올라왔던) 동일한 GPU를 사용하시는 분의 글을 발견:
https://breakthedays.tistory.com/354

 

[Keras 딥러닝] CUDA, cuDNN 설치하여 GPU 환경 구축하기 (Windows, 가상환경 사용, GTX 1060)

약 열흘간 GPU 환경 구축하려고 별 짓 다했다.포기할까도 생각했는데 학습 시킬때 마다 느려터져서 속이 터지고,멀쩡히 달려있는 GPU 가 놀고 있는 꼴이 보기 싫어서 이것저것 다 시도해보았다. 

breakthedays.tistory.com

 

천천히 읽어가다 보니 compute capability(cc)라는 것도 있고, GTX 1060은 6.1 정도였다.

 

쭉 읽다보니 이 분은 설치하신게 CUDA 8.0....

 

pytorch, pyg 공식 install 화면에 나와있는 최소 선택지가 11.8 이었던 지라 다시 10 버전대를 설치하기엔 삭제하느라 날린 1시간이 헛발질 하는 셈이었기에 그건 피하고 싶었다.

 

결국 인터넷을 찾던 중 다음 글을 발견:

https://forums.developer.nvidia.com/t/minimum-required-cuda-version-by-gpu/276955/2

 

Minimum required CUDA version by GPU

If you know the compute capability of a GPU, you can find the minimum necessary CUDA version by looking at the table here. The compute capabilities of those GPUs (can be discovered via deviceQuery) are: H100 - 9.0 L40, L40S - 8.9 A100 - 8.0 A40 - 8.6 Looki

forums.developer.nvidia.com

 

핵심은

"For older GPUs you can also find the last CUDA version that supported that compute capability. For example, if you had a cc 3.5 GPU, you could determine that CUDA 11.x supports that GPU (still) whereas CUDA 12.x does not."

 

즉 나의 소중한 GTX 1060은 여전히 CUDA 11.x의 support를 받을 수 있다는 의미😊

그렇게 CUDA 11.8을 다운받아 설치하고...

 

cuDNN도 다운받아서 CUDA 설치 경로(C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8)에 복사를 하고...

 

 

완료 :)

 

뒤이어 anaconda를 설치하고, 환경을 만들어 torch를 우선 설치.

 

GPU가 잘 잡힌다.

 

GPU까지 잘 잡히는걸 확인한 후에 pyg를 설치하려고 하니...

 

 

???

 

pytorch를 cpu 버전으로 downgrade 시키려고 한다.

 

그래서 무슨일인가... 하고 바로 공식 github의 issue 쪽을 찾아보니

https://github.com/pyg-team/pytorch_geometric/issues/8948

 

cpu version instead of cu121 · Issue #8948 · pyg-team/pytorch_geometric

😵 Describe the installation problem I tried to run conda install pyg -c pyg expected behaviour: installing the following file linux-64/pyg-2.5.0-py311_torch_2.2.0_cu121.tar.bz2 instead it is trying...

github.com

 

"it could be the timestamps of the pyg versions that leads to conda preferring cpu over cuda as conda tries to select the latest build."

 

ㅋㅋ;; 이런 경우는 또 처음 보는 듯 했다.

 

그래서 대안책으로 적어준 방법대로 conda install pyg=*=*cu* -c pyg를 하니

 

 

(비록 .1 downgrade 되긴 했지만) 잘 되었다 :)

 

 

 

 

pytorch, pyg까지 설치를 마친 후 확인하니 온전히 설치가 잘 된 듯 하다.

 

아직 코드를 작성해서 간단한 무언가를 확인해보진 않았는데, 우선 환경 내에서 패키지가 load되고 실행되 잘 되니 별 문제는 없으...리라 생각한다.

 

 


 

설치하면서도 정말 여러 생각이 많이 들었다.

 

졸업준비를 할때 사용했던 환경이 pytorch 1.12.1에 CUDA 11.6 이었는데,

1년 정도 지난 지금은 벌써 pytorch 2.5.1에 CUDA 12.4가 나오고...

 

트위터 공부용 계정으로 둘러볼때 flash attention이 pytorch에 추가된다는 말을 봤던 것 같은데, 이게 벌써 2.5.1에 실험적으로 들어가있고...

 

이쪽 field의 발전 속도가 빠르다는 걸 알고는 있었지만

실제로 근 1년 정도 소식으로만 드문드문 접하다가 다시 설치하면서 둘러보니

그 속도가 정~말 빠른 것 같긴 하다. 뭔가 잠깐 안한 사이에 엄청나게 도태된 느낌...

 

3GB VRAM 으로 뭐 얼마나 대단한걸 할 수 있을까... 싶기도 하지만

llama.cpp도 있고, 여러 API들이 정말 많이 나왔으니

여태 슬쩍슬쩍 둘러보기만 했던 traditional한 RAG, GraphRAG 도 천천히 공부해보고, 미루고 미뤘던 GNN&추천시스템 모델/알고리즘 들을 하나씩 차근차근 작성하려고 한다.

얼마나 잘 해낼 수 있을진 모르겠지만... 그래도 시작이 절반이라는 말이 있지 않은가. 잘 해낼 수 있을 것이라 믿는다 :)

 

 

E.O.D.

어느덧 24년이 끝나간다.

 

작년 이맘때 즈음 논문 심사도 마치고, 기말시험을 보고, 부산 벡스코에서 개최된 학술대회에서 발표를 하고... 

 

24년 전체를 돌아보면 학업이나 커리어 쪽으로는 별다른 점은 없지만, 수 많은 추억을 만들 수 있었던 한 해 였던 것 같다.

 

촬영했던 사진들을 돌아보며 기억에 남을만 한 이벤트(?) 같은 것들을 기록으로 남겨보고자 한다.

 

 

 

1월

  • 공식적으로 연구실 출근 X. 이때를 이후로 거의 1주일에 3번은 오락실에 다녔는 듯 하다.
  • 후배가 아이패드를 구매하면서 이전에 사용하던 샤오미 패드를 프로세카를 보다 쾌적하게 플레이하기 위해 싼 값에 넘겨받아 왔다. 
  • 동아리 친구&후배들과 잠깐 메이플랜드(클래식 메이플스토리)를 플레이.
    • 친구가 스피어맨, 후배1은 썬콜, 후배2는 불독, 나는 클레릭
    • 당시엔 클레릭 사냥터가 마땅치도 않았고, 오락실을 더 자주갔던 지라 자연스럽게 폐사... ㅋㅋㅋ
      집에 있던 옛날 메이플 가이드북을 보며 스킬트리를 어떻게 할지 이야기하기도 했다.
  • 함께 졸업한 후배와 거의 주에 한두번 꼴로 음주 :)
  • 둘째형의 결혼 & 동아리 후배들의 결혼.
    • 하필 후배 결혼식 일정이 둘째형 결혼식 일정과 같은 날이었던 지라, 둘째형 결혼식을 마친 후 바로 후배 결혼식에 찾아갔던 기억이 난다.
  • 게임적으로는 팝픈과 투덱을 참 열심히 한 듯 하다. 자주 가는 오락실에 방송 송출 컴퓨터가 있어서 이때부터 클립을 남기기 시작한 듯...
    • 팝클래스가 96.60 즈음 이었는데, 친구들의 권유로 슬슬 49를 한번씩 건들기 시작하면서 팝클래스가 많이 오른게 한 몫을 한 듯 하다.
     

담당캐릭터 사진도 한장..^^

 

 

2월

  • 18년도에 전역하면서 구매했던 의자를 바꾸고, 새 의자를 구매.

좌측이 새 의자, 우측이 기존 의자.

  • 졸업을 앞두고 동아리 친구&후배들을 불러서 음주.

친구가 들고온 버번, 결혼했던 후배가 선물로 사다준 체코 술, 23년 가족여행 때 사온 노르웨이 술(일명 생명수), 둘째형이 주고 간 술

  • 졸업식. 연구실 출근을 안한 약 한달 사이 처음보는 후배분이 새로 들어와있어서 조금 놀라웠다.
    • 참.. 여러 복잡한 감정이 들었던 것 같다. 배운것도 많고 느낀것도 많고 소중한 인연들도 만날 수 있었고. 여러가지 해프닝이 많았어서 그런지 군 생활 처럼 2년이라는 시간이 참 짧았던 듯 하다.

^^...

  • 1주뒤에 있던 후배 졸업식에도 방문. 이전에 생활하던 연구실에 방치해뒀던 과잠을 동아리방에 기증(?)
  • 게임적으로는 팝픈에서 설상단화 로 48 첫 AAA를 달성했던 점이 참 기억에 남는 듯 하다.
    (https://youtu.be/XyhiYv2g7oo)

 

3월

  • 여전히 오락실-음주 를 번갈아가며 방탕한 생활을 지냈다. ㅋㅋㅋ
  • 공항공사에 근무중인 후배의 권유로 제천 포레스트 리솜으로 1박2일 짧은 여행을 다녀왔다.

야외 온천풀장. 날이 추웠지만 물이 따뜻해서 엄청 좋았던 기억이 난다.

  • 졸업한 기념으로 오랫동안 만나지 못했던 대학교 동기 친구를 만나러 용인 기흥 방문.
    • 친구 자취방에서 오랫동안 못 나눴던 이야기도 많이 나눠보고, 오랫만에 같이 음주도 진득하게 한 듯 하다.

자취방 근처에 먹거리 집이 마땅히 없어서, 안주를 전부 배달로 먹었었다.

  • 동아리가 생긴지 벌써 10주년이 되어서, MT때 항상 갔던 천생연분마을로 방문했다.
    • 졸업한 선배들과 동기&후배들도 오랫만에 만나고, 처음보는 신입생 후배들도 많이 볼 수 있어서 신선했던 기억이 난다.
    • 음주하며 같은 과 후배들과 이런저런 이야기도 많이 나누고, 음주도 재밌게 하고, 여러모로 추억에 잘 남은 듯 하다.
  • 게임적으로도 여러 진전(?)/발전(?)이 있었던 것 같다.

 

4월

  • 부모님과 함께 합천/거창/예산/아산 으로 여행을 다녀왔다.
    • 예전에 여행 1일차 글을 썼다가, 적을 말이 너무 많아지다 보니 2일차부터 엄두가 나질 않아 그냥 비공개 처리하기도 했다 😅 여행 글들 잘쓰시는 분들이 참 존경스럽던 때 였다.
    • 벚꽃 구경도 하면서 해인사 팔만대장경도 처음 보고, 황계폭포, 수승대, Y자 출렁다리, 수덕사 등등... 여러 곳을 둘러볼 수 있어서 정말 기억에 잘 남는 듯 하다.

실제로는 처음 본 팔만대장경. 교과서에서나 보던 문화유산을 직접 눈으로 보니 신선한 느낌이 들었다.

  • 큰형의 진급 기념으로 온 가족이 모여 한우를 먹었다. 항상 지나가는 길에서만 보던 임가네 한우마을에서 먹어봤는데, 가격을 생각하니 글쎄..라는 생각이 들었다.
  • 상반기 작계훈련에 다녀왔다. 작년까지만해도 학생 신분이었어서 학생 예비군으로 다녀왔는데, 학생이 아닌 예비군은 이번이 처음이라 많이 신선한 느낌이 들었다.
  • 대학교 동기를 통해 알게된 친구들(사회 친구들?)과 만나서 집에서 음주. 만난 날에 오락실에 갔다가 고등학교때 같이 태고를 플레이하던 친구도 정~말 오랫만에 만나서 반가웠었다 😊
  • 게임적으로도 많은 발전(?)이 있었던 듯 하다.
    • 팝픈 클래스가 97을 넘어갔다. 49 입문곡이었던 시노기 이후로 금방 클리어를 할 수 있을것 같았지만 도저히 안되었던 배드엔드신드롬(https://youtu.be/-OvFpwwka60)도 클리어 한 기억이 남는다.
    • 이때즈음 부터 사볼에서 간간히 클립을 남기는 재미가 들린 듯 하다. 2~3 시절 열심히 했던 추억을 되살펴보면서 자켓도 뽑아보고, 당시엔 클리어가 정말 힘들었던 노래(https://youtu.be/zlMn7EGKTnI)들도 클리어해서 영상으로 남겨보고...
    • 프로세카 에서 APPEND 레벨을 처음으로 풀콤보를 해보았다(https://youtu.be/8QXLzPkEdNY)
    • 투덱에서도 A~A+ 라인이 이전보다 잘 되기도 하였고, S라인을 슬슬 건드려보기 시작한 듯.
    • 아주르레인(벽람항로)에서 드디어 휴스턴을 얻었다 :)

술먹다가 깜짝놀라서 핸드폰으로 급하게 촬영했던 기억이 난다.

 

5월

  • 일본에서 생활중인 동아리 동기 친구가 한국에 잠시 돌아와서 다같이 모여서 음주.
    • 졸업한 선배들도 오랫만에 뵈고, 동기 친구들도 오랫만에 보고, 후배들도 오랫만에 보고... 
    • 다음날 점심으로 홍대 애슐리를 가보려 했다가, 대기줄이 너무 길어서 두끼떡볶이에서 점심을 먹었다.
    • 먹고 나오면서 헤어지는 길에 친한 선배와 갑자기 동인음악 행사인 M3에 한번 가보자! 라는 합의가 갑작스레...
  • 어린이 날을 맞이해 동아리 후배들과 함께 정~말 오래간만에 범계에 놀러갔다.
    • 예전에 항상 같이 밤샘하던 후배 둘은 마찬가지로 밤샘을 하고, 나는 피곤해서 귀가조를 선택했다 ㅠ
  • 정~말 오랫만에 화정에서 같이 리듬게임하는 지인분과 저녁 겸 술을 한잔 했다.
    • 지인 분의 소개로 다른 분을 알게되었는데... 이 분이 무려 대학교 후배 & 같은 과 후배 분이셨다 ㅋㅋㅋ;; 

오락실 근처에 꽤 오래 있던 부자곱. 상당히 맛있었다.

  • 부모님과 오랫만에 직천지로 밤낚시를 다녀왔다. 비록 손바닥 만한 붕어 1마리밖에 못잡았지만... 만족스러웠다 :) 

낚시터에서 저녁. 낚시도 좋지만 역시 간이 캠핑(?)이 정말 좋다.

 

  • 그리고 항상 못해도 주에 2~3번은 음주. 사진을 되돌아보니 놀러가거나 약속나갔거나 한 날을 제외하면 거진 술 사진밖에 보이질 않는다 😅
  • 게임적으로 역시나 많이 발전했는 듯. 그도 그럴게 주에 2~3번을 계속 다녔던지라...
    • 팝픈에서는 43 무비스타 점수를 정말 높게 받았던 기억이 난다. 아직까지도 이 점수를 못넘기고 있다 :(
      (https://youtu.be/rNcGSijB1c8)
    • 투덱에서는 처음으로 S 라인 하드클을 달성했다. 정말 기뻤다.
      (https://youtu.be/ff-h6vU1vuI)
      아레나 랭크 A4를 처음 달성해봤다.
      (https://youtu.be/q92x1BNEPQs)
      그리고 Programmed 시리즈 4개를 전부 풀콤보를 했다. 개인적인 버켓리스트 중 하나였는데 정말 기뻤다 :)

언젠가 Programmed Universe도 빨리 이식이 되었으면.

 

6월

  • 부모님과 큰 형네 가족과 함께 영월 김삿갓 계곡 캠핑장에 방문.
    • 계곡..을 마지막으로 간게 아마도 초등학교 때 였던 것 같은데, 항상 바닷가만 가다가 계곡을 가니 정말 신선했다.
    • 데크에 텐트를 치고, 바로 앞 조그만한 계곡에서 물놀이도 많이 하고, 사온 소고기&돼지고기도 먹고, 이틀에 걸쳐 청하 한박스도 다 비우고 ㅋㅋ...

김삿갓 계곡 캠핑장 데크에서 본 계곡. 물이 정말 깨끗하고 시원했다.
돌아오는 길에는 김인수할머니순두부 라는 집에서 밥을 먹었다. 상당히 맛있었던 기억이 난다.

  • 사용중이던 DJ DAO FP7 컨트롤러의 스위치가 이전부터 너무 말썽이었어서(이중인식 등), 스위치를 구매해서 교체.
  • 연구실 동기와 후배들에게 연락이 와서 오랫만에 만나 술을 한잔 했다.
    • 졸업식 때 처음 봤던 후배분과도 얘기하고, 연구실 근황도 듣고...
    • 동기가 이 당시엔 미국으로 넘어가기 전 이었는데, 나보고 연구실 출근을 바로 안한게 정말 좋은 선택이었다고 했던게 기억에 잘 남는다 ㅋㅋㅋㅋ
    • 이날 2차까지 갔다가, 과음해버리는 바람에 연신내에서 버스를 타고 돌아가던 중 깜빡 잠이 들었다. 눈을 떠보니 중부대학교 근처...

당시 방문했던 제주 도로담. 고기가 상당히 맛있었던 기억이 난다.

  • 이 외에도 역시나 남아있는 것은 술 사진 ㅋㅋ... 진짜 술을 많이 먹긴 했다.
  • 오락실을 꾸준히 다녀서, 역시나 실력이 꾸준히 오르는 듯 한 느낌이 많이 들었다.
    • 팝픈에선 49 가이젤하우스가 바로 클리어 되어서 많이 놀라웠다.
      (https://youtu.be/gyBqg9h1PPQ)
    • 투덱에선 입문 시절 부터 꿈꿔왔던 노래 NZM을 드디어 하드클을 해보았다. 정~~말 감격스러운 순간이었다.
      (https://youtu.be/9hHVve6OQrU)
    • 사볼에선 예전에 엄~청 쥐약이었던 Xepher GRV를 S 클리어 할 수 있었다. 시간이 지나니 노트 처리력이 많이 늘은 것 같아 감회가 새로웠는 듯.
      (https://youtu.be/6G1xrvn2MVs)

7월

  • 인생 처음이자 마지막인 (학생 예비군이 아닌) 동원 예비군 참석. 하필 장소가 대학교때 갔던 대화 훈련장이어서 어색한 느낌은 많이 들지 않았다.
    • 더군다나 비가 왔던 날이라 교육도 전부 실내교육으로 진행하고, 사격 등 평가도 전부 개인별 평가로 했었다.
  • 동반입대를 같이 했었던 고등학교 때 친구를 불러서 집에서 음주. 이전엔 대조동에 살았었던 친구인데, 이사를 풍무 쪽으로 가버리는 바람에 만날 기회가 적었지만 오랫만에 봐서 정말 재밌었던 기억이 난다.
  • 5월달에 봤던 일본에서 생활중인 대학교 동기 친구가 다시 놀러와서 홍대에서 모였다.
    • 홍대의 작은 룸을 하나 빌려서 밤새도록 음주. 이날 처음으로 천사의 유혹 이라는 고구마 소주를 처음 먹어봤다가 신기한 맛에 깜짝 놀랐던 기억이 난다.

그날 비웠던 술. 친구가 사온 우메슈도 정말 맛있었다.

  • 외에도 역시 남겨진 사진은 집에서 먹은 술 사진... 이 정도면 알코올 중독이 아닌가 싶기도 하다.
    • 밤 11시에 음주를 시작해서 유튜브로 디제잉 영상을 보면서 계속 먹다보니 아침 6시에 찍은 사진도 있다. 다시봐도 참 대단했는 듯.
  • 게임적으로는 꾸준히 올라간 듯 하다. 팝픈에서 가장 많은 성과를 봤었는 듯.
    • 팝픈에서는 48에 남아있던 노래들을 이것 저것 치울 수 있었다. 특히 레슨을 잡아서 다행이었다...
      (https://youtu.be/nHmdDaUQReo)
      그리고 팝픈 입문 때 부터 꿈꿔왔던 노래인 Vinculum stellarum을 처음 클리어 해봤다. 투덱에서 NZM를 하드클 했을 때 만큼 정~~말정말 기뻤던 기억이 난다.
      (https://youtu.be/YqM-NKdGjFM)
      추가적으로 49 짠게이지 노래도 처음 클리어해봤다. 아마 기억상 이 날 49를 8개나 클리어했었는 듯 하다.
    • 사볼에서는 먼 옛날에 1 NEAR를 봤던 노래를 드디어 PUC을 보게 되어서 정말 기뻤다.
      ( https://youtu.be/AXrUhk3OdfA )
    • 투덱에서는 11레벨 AAA 갯수가 100개를 넘겨보았다. 

훈장 시스템 추가가 된 덕에 뭔가 보는 맛이 좋아졌다.

 

8월

  • 부모님과 둘째 형네와 함께 인제 필례약수 온천 캠핑장을 다녀왔다.
    • 아..마 기억상 6~7월 즈음 아버지께서 캠핑 장비를 이것저것 주문하시기도 하셨고, 둘째 형네 와는 이번 여름에 마땅히 놀러가질 않아서 일정을 맞춰 놀러 다녀왔다.
    • 2박3일 중 2번째 날은 둘째 형네와 같이 예전에 갔었던 고성 삼포 해수욕장에도 다녀왔는데, 예전에 비해 바닷물이 조금 덜 시원한 느낌이 많이 들었다.

설치한 텐트.
몇년만에 다시 온 삼포 해수욕장. 사람이 정말 많았다.

  • 부모님이 친구분들과 함께 호주/뉴질랜드 여행을 가시는 바람에, 친구들 여름 정모를 우리집에서 개최했다.
    • 천안에서 올라온 친구, 대구에서 올라온 친구, 부산에서 올라온 친구, 거의 15명 정도가 모였던 듯 하다.
    • 마침 대구에 사는 친구 한명이 주류 박람회에서 이런 저런 술을 눈들여 놨다가, 정모 직전에 우리집으로 배송시켜놔서 그 술도 정말 맛있게 먹었던 기억이 난다.

이런 저런 술도 많았지만, 가장 기억에 남았던 술. 상당히 양주같았다.

  • 뒤 이어서 바로 그 다음주에는 대학교 동아리 동기 친구 & 후배들을 불러서 음주 파티.
    • 대구로 내려갔던 같이 졸업한 후배도 오랫만에 만나고, 한동안 못 만났던 안산 쪽 사는 후배도 만나고 오랫만에 다같이 모여서 정말 정신줄 놓고 놀았던 기억이 난다.
    • 대구에서 올라온 후배는 2~3일 정도 더 묶다가 돌아갔다.

다같이 모여서 음주

  • 게임적으로는 잠시 정체기가 왔었던 때 이기도 하다.
    • 투덱에서 이상하리만큼 시선이 맞질 않고, 판정이 너무 튀어서 거의 손을 대지 않았던 듯. 실제로 남겨둔 사진도 많이 있지가 않다.
    • 대신 BMS의 비중을 높이다 보니, ★9 Lapis를 하드클 하기도 했었다.
      (https://youtu.be/YAWwgiih4bQ)
    • 팝픈에서의 비중이 가장 큰 듯 하다. 팝클래스가 이 한달동안 97.48에서 97.69까지 올라왔다.

제일 놀라웠던 영덤프. 예전에 친구의 추천으로 3번 플레이 한 후에 전혀 건들질 않고 있었는데, 묵혀두고 플레이 하니 클리어가 되어서 많이 놀라웠다.

 

9월

  • 시골로 온 가족이 추석 전 벌초를 하러 갔다.
    • 밤 늦게 출발해서 새벽에 도착한 후, 새벽 5시~6시 즈음 기상해서 벌초를 마치고...
    • 저녁은 이전때와 마찬가지로 마당에 친척들이 모두 모여서 고기 파티(?)를 했다.
    • 다음 날 형들은 먼저 귀가하고, 나는 부모님과 함께 문경-수안보로 들러서 온천호텔에서 하룻밤을 더 묶고 귀가.

고모가 일하는 상감한우 고기. 언제나 먹어도 정말 맛있다.
아마 작년?제작년?즈음 부터 시골집에 눌러 앉은 고양이. 사람 손을 타서 그런지 피하지도 않고 만져도 별로 싫어하는 눈치를 주지 않아서 정말 귀엽다.

  • 아버지께서 이전에 친구분들과 다녀오셨던 삼팔패키지 라는 것을 큰형네와 가게 되었다.
    • 알고 보니 삼팔횟집이 현역 시절 군부대 바로 앞에 있던 횟집.... 많이 신선했다.
    • 하조대에 도착해서 정~말 오랫만에 하조대짬뽕을 먹고, 조카를 데리고 해수욕장에서 한두시간 정도 놀고, 숙소에서 쉰 후 횟집에서 모듬회를 먹었다. 숙소숙박+모듬회식사 패키지로 다녀왔는데, 정말 만족스러웠다.
    • 다녀오는 길에는 광치산 자연휴양림에 들러서 1박을 더 하고, 양구재래식손두부 라는 곳에서 밥을 먹고 충주댐을 구경한 후 귀가했다.

삼팔패키지에서 저녁에 먹었던 모듬회. 무한 제공이 가능하다곤 하는데, 양이 양인지라 리필은 조금 힘들었던 기억이 난다.
양구재래식손두부. 원래 이런 류의 음식은 별로 내켜하질 않는데, 맛이 상당히 맛있어서 밥을 리필해서 먹었을 정도로 기억에 남는다.

  • 언제나 있는 음주사진 ^^;;
  • 그리..고 이때부터 하반기가 시작되어 본격적인 취준도 함께한 기억이 난다.
    • LG도 열리고, SK도 열리고, 한투도 열리고, CJ도 열리고... 
    • 바쁘지 않던 졸업 직전이나 올해 초 즈음에 어학 성적을 받아놨어야 했는데, 부랴부랴 OPIc을 신청하고 시험 전날에 유튜브를 보며 (순수 시간만 따지면 대략 6시간?) 공부를 한 후 시험을 봤다.
  • 게임적으로는 약간의 변화(?)가 한번 있었다.
    • 거의 한달 정도 투덱을 하지 않았다가, 설정을 바꿔보자 한 후에 리프트&서든을 바꾸고, 녹숫을 바꾸고... 다행히도 한번 바꾼 후에 바로 시선이 맞았다. 덕분에 Fly Above도 인생 최고점수...가 나오긴 했었다.
      (https://youtu.be/7geONeiJcvM)
    • 팝픈에서는 49 카우보이를 깼던게 가장 기억에 남는 듯.
      (https://youtu.be/H1C5gQJ8l9s)

 

10월

인생에서 절대 잊지 못할 여행도 한번 다녀오고, 이런저런 해프닝이 정~말 많았던 달 이었는 듯 하다.

 

  • 부모님과 둘째 형네와 함께 직천지로 밤낚시를 갔다.
    • 즐겁게 고기를 구워먹으면서 다같이 술을 한잔 하고 있는데, LG에서 나온 불합격 소식... 술이 들어가서 그런지 뭔가 아쉽고 슬프다 라는 느낌 보다는 에이 그럼 그렇지~ 했던 기분이 더 들었던 것 같다.

숯불에 소고기를 먼저 먹은 후, 이어서 먹은 삼겹살. 역시 밖에서 먹는 고기는 참 맛있다.

  • 이후 몇일 뒤엔가에 SK 합격 소식을 듣고 기뻐했던 기억이 난다.

어떻게 서류가 붙었을까... 하는 의문이 들었지만, 그래도 기쁘긴 기뻤다 :)

  • DMC에서 사는 동아리 동기 친구가 후배와 다른 동기 친구를 불러서 옥상에서 고기 파티를 했다.
    • 그 다음날이 SK 필기 시험 날 이긴 했지만, 그보다 훨씬 전에 잡아둔 일정이라 그냥 다녀왔다. 하루 가서 고기만 먹고 온다고 결과가 크게 달라질 것 같다는 느낌도 들지 않았고, 후회는 없다.

화력이 약해서 약간 훈제(?) 스타일로 먹었던 기억이 난다.

  • SKCT를 보고, 다음날에 챗봇을 활용한 코딩테스트/직무테스트 (?) 같은 걸 보고... 아마 기억상 2주가 조금 되기 전에 결과가 나왔던 것으로 기억한다. 결과는 뭐 당연히...
    • 학부 졸업했을 당시 SSAFY 5기? 시험을 봤을때도 이런 류의 시험은 진짜 못하겠다 라는 생각을 했는데, 적성시험이 하필 이런 스타일이었고 ㅋㅋ... 준비를 열심히 하긴 했지만 참 여러모로 씁쓸했다.
  • 후에 고등학교 친구 한명이 군무원에 합격했다는 소식을 듣고, 모두가 홍대에 모여서 밥을 먹고 당구장/보드게임카페에서 놀았다.
    • 당구를 칠 줄 아는 사람이 없어서 포켓볼을 치긴 했지만, 모여서 항상 PC방만 가다가 나름 건전한(?) 유흥을 하니 상당히 재밌었던 기억이 난다.

군 입대 전 동아리방에서 동기 친구들과 자주했던 뱅! 이 생각나서 친구들과 플레이. 오랫만에 하니 옛 생각도 나고 참 재밌었다.

  • 그리고 아마 SK 결과가 나오기 몇일 전? 즈음 CJ 서류 합격 메일이 도착. 그래도 서류가 두 군데 뚫리긴 한게 참 신기했다.
    • 메일을 받자 마자 서점으로 부랴부랴 달려가서 문제집을 구매. 몇일 내내 책상에 앉아서 모의고사를 주구장창 풀었던 기억이 난다.
    • 근데 제일 큰 문제는 5월에 동아리 선배와 이야기 했던 M3 일정을 이미 10/24~10/28 로 짜놨는데, 필기 시험이 하필 10/26 ㅋㅋㅋㅋㅋㅋ
    • 그 날이 쿠사츠 온천 료칸에 묶는 날이라 이걸 어찌해야하나 하다가, 결국 체크아웃 시간을 미루고 노트북을 챙겨가서 숙소에서 시험을 봤다. 참... 절대 잊혀지지 않을 추억(?)이 하나 늘어난 듯 ㅋㅋㅋ
    • 여행을 다녀온 후 리듬게임 갤러리와 Manjuu 채널에 후기 글을 작성했고, DC에 쓴 글은 정말 감사하게도(?) 실시간 베스트에 올라갔다. 참 신기한 경험이었다.
      (https://gall.dcinside.com/board/view/?id=dcbest&no=276872)
      (https://arca.live/b/manjuugame/119980354)
    • 블로그에도 후기글을 바로 쓰고자 했지만, 두 군데에 글을 쓰고 나니 귀찮기도 귀찮아지고 계속 미루게 되었다. 추후 하루하루 일정을 천천히 써가도록 노력할 예정 :)

쿠사츠 온천 료칸에서 아침식사 후 시험 준비. 다시 생각해봐도 참 여러모로 대단했는 듯.

  • 게임적으로는 또 한번의 고비가 찾아온 듯 했던 때 였던 것 같다.
    • 이전에 맞춰놨던 투덱의 설정이 다시 안맞기라도 했는지, 시선이 너무 흔들려서 일본여행 전 까지 거의 손 대지도 않았던 기억이 난다.
      이때 가장 기억에 남는건 역시 일본여행 갔을 때 WGC에서 삭제곡들을 플레이 했던 것. V35와 Look To The Sky를 플레이 했던게 정말정말 기억에 오래 남는다. 플레이 하는 동안 감격스러워서 눈물이 나올뻔 했었다.
      (https://youtube.com/shorts/wCSz5KvxmWk?feature=share)
      (https://youtube.com/shorts/X2bxlBABQd8?feature=share)
    • 오히려 사볼이 잘되었는 듯 하다. 18 989였던 노래들이 갑자기 슬슬 뚫리기도 했고, 그러다 보니 난생 처음으로 볼포스 랭크업도 볼 수 있었다.
      (https://youtube.com/shorts/507krbSXKak?feature=share)
      그리고 4 시절 해금만 겨우 해놨던 20레벨 I도 처음으로 클리어 할 수 있었다. 감회가 정말 새로웠다.
      (https://youtu.be/EfhJRWfx640)
    • 팝픈에서는 49 마플럼을 클리어 했던게 가장 기억에 남는 듯 하다. 항상 후반에서 피 유지가 안되었는데, 이때는 어찌저찌 유지가 잘 되었었는 듯.
      (https://youtu.be/LLz0vega_nI)

 

11월

  • 아버지 생신 때 온 가족이 모여서 저녁을 먹고, 일본 여행때 사온 닷사이23을 전부 비우고 천사의유혹도 어느정도 먹었던 기억이 난다.
    • 솔직히 닷사이를 이날 전부 비울 줄은 생각을 못했다... ㅋㅋ

아버지 생신 때 먹었던 술.

  • 부모님과 함께 산음자연휴양림에 다녀오고, 돌아오는 길에 포천 신북온천에서 하룻밤을 묶었다.
    • 산음자연휴양림 가는 길에 먹었던 돼지불백이 정~~말 맛있었던 기억이 난다.
    • 마찬가지로 가는 길에 홍천강 막걸리 양조장이 있어서, 제일 큰 패트병을 4통에 1만원에 사오기도 했다.
    • 포천 가는길엔 화적연도 처음 가보고, 포천 시내에서 닭강정을 사면서 시내도 처음 잠깐동안 구경해봤다.
    • 돌아오는 날엔 이동갈비를 먹고, 국립수목원도 처음 들러서 여러 구경을 했다.

식당 가기 직전에 보였던 막걸리 양조장. 딱 이 3종류만을 판매하고 있었다. 가격은 아마 기억상 4개/6개/8개에 1만원 이었던 것으로 기억한다.
식당에서 먹었던 돼지불백. 상당히 맛있었는데, 밑반찬도 정말 맛있었다.
돌아오는 날 포천에서 먹은 이동갈비. 아마 초등학교때 인가 이후로 처음 먹는 듯 했다.

  • 취준 쪽으로는 좋은 소식이 없었다. 아무래도 SK와 CJ에 모든 운이 다 들어간게 아니었을까... 하는 생각이 들 정도였다 ㅋㅋㅋㅋ
    • 합격했던 서류를 알맞게 수정한다고 하긴 했는데 아무래도 내가 놓친 부분이 좀 많았는지, 많이 부족하게 적었는지 작성했던 서류들이 모두 떨어진건 좀 씁쓸하긴 했다 😓

11월 말까지 났던 발표들.

  • 작은 형수님 생일에 부모님과 둘째 형네와 함께 삼송역 근처 흑염소 집에서 식사를 했다.
    • 항상 가던 원당 흑염소 집이랑은 뭔가 색다른 맛 이었는데, 맛이 없는건 아니었고 다른 느낌이라 맛있었다.
    • 식사 후에 갑자기 작은 형수님이 노래방 이야기를 꺼내셔서, 가족끼리 거의 10년?만에 노래방을 간 듯 하다.

전골과 함께 먹었던 수육. 방문한 날 주방 이모께서 사정이 생겨 사장님 혼자서 주문을 준비해주셨다.

  • 그리고 언제나 있는 음주사진. 그래도 오락실을 올해 초에 가던 것 만큼 자주 가질 않아서 그런가, 사진의 개수가 많이 줄어든 것 같긴 하다.
  • 게임적으로는 큰 추억거리가 마땅히 없는 듯 하다. 자잘자잘 하게 있는 듯 한 느낌?

 

12월

  • 대전에 내려가는 같은 시기 대학원을 졸업한 동아리 후배 겸 친구(?)가 불러서 신도림에서 저녁 겸 술 한잔을 했다.
    • 이 날 번화가 같은 곳을 다닐 때 보이던 생마차 라는 가게를 처음 들어가봤는데, 되게 일본에서 갔던 술집 느낌이 나서 신기했던 기억이 난다. 

닭날개 튀김이 1개에 990원? 인가 하는데, 당연히 낱개로는 팔지 않고 10/20개 단위로 팔았던 것 같다.

  • 해가 넘어가기 전 동아리 후배 두명과 함께 주안에서 만나서 오랫만에 재밌게 놀았다.
    • 후배가 항상 이야기하는 돈까스 집이 있어서 가보려고 했는데, 하필 토요일이 휴무일이어서 가보지 못한게 좀 아쉬웠다. 다음에 가는 것으로 :)
  • 아마 6월인가에 들어왔던 세금 환급액으로 여태 버티고 있었는데, 드디어 바닥이 보이기 시작.
    • 결국 코로나 전에 친구와 한번 가봤던 고양 쿠팡으로 하루 단기 알바를 다녀왔다.
    • IB로 들어가서 물건을 채워넣고, 구내식당에서 밥을 먹고, 물건을 채워 넣고...
    • 신기했던 점은 그 당시엔 셔틀버스가 없었던 것으로 기억하는데, 이번에 갔을 땐 출/퇴근 시 셔틀버스가 바로 집 근처에 세워주어서 출퇴근이 많이 편했던 기억이 난다.
  • 크리스마스 전에 부모님이 집을 잠시 비우시는 것을 기회로, 동아리의 후배 두명을 불러서 음주 파티를 했다.
    • 조금 남아있던 생명수도 맛 보여주고, 조금씩 남아있던 위스키들도 비우고...
    • 함께 유튜브를 보면서 술을 먹고 수다떨다 보니 어느새 아침 6시였다 ㅋㅋㅋㅋㅋ
    • 다음날(이브) 동아리 선배가 맥주 한잔 할 사람들은 만나서 놀다가 맥주한잔 하자고 하셨는데... 숙취가 너무 심해서 하루 종일 누워있었다 😥

이날 먹었던 술. 다시봐도 정말 많이 먹은 듯 하다.

  • 취준 쪽으로도 한 차례 벽(?)/현실을 맛본 듯 했다.
    • 이전에 넣었던 서류도 마저 떨어졌고, 뭐 그럼 그렇지 하는 기분이 들었다.
    • 조금 충격이었던 점은 상시 채용으로 열려있던 넥슨이었다. 학부 졸업 당시엔 서류-과제 전부 통과했다가 인생 첫 면접이었던 지라 많이 긴장해서 떨어졌고, 작년 10~11월 즈음엔 서류는 통과하고 과제에서 너무 새로운(?) 모델을 사용했다가 떨어졌었다. 그래도 2차례 모두 서류는 되었었으니 한층 더 보완하고 다듬어서 뚫어야지 하며 주변 친구들의 피드백도 많이 받고 제출하고 당연히 서류는 통과 되겠지 했는데, 떨어졌다 😥 
      상시는 역시 상시구나... 라는 느낌이 많이 들었다.
    • 해가 넘어가기 전 그래도 아직 열려있는 공고가 있어서 일단 작성해두긴 했는데, 1월 초에 나오는 결과가 어떨지 참 기대가 된다. 어짜피 될 거 같은 느낌은 들지 않지만... ㅋㅋㅋㅋㅋ
  • 게임적으로는 뭔가 저점을 잘 끌어올린 듯 했다.

 

글을 적으면서 다시 되돌아보니 여러 추억을 정말 많이 만들었던 한 해 였다는 생각이 든다.

 

가족과 보내는 시간이 정말 많이 늘어났고, 그만큼 가족여행도 자주 다녀온 듯 하고...

 

일본 여행을 갔던 게 군 입대 전 16년 당시 동반입대 하는 고등학교 친구와 함께 갔던 것이 마지막이었는데, 몇년 만에 다녀와서 그런지 기억에 정말 오래 남을 듯 하다. 무엇보다 꿈꿔왔던 것 중 하나인 M3 행사에 참석해볼 수 있었던 것이 정말 좋았던 것 같다.

 

커리어 적 으로는 흠.. 글쎄 라는 생각이 많이 들기는 한다.

취업 시장이 어렵다 라는 말이 돌기는 했지만, 거의 예전부터 항상 있던 말 이기도 하고, 운 보다는 실력이 많이 부족하다는 느낌이 많이 들기도 했다.

 

게임적으로는 참 만족스러운 한 해 였던 것 같다.

14년에 BEMANI 시리즈를 본격적으로 입문하면서 그 당시부터 꿈꿔왔던 목표곡인 NZM도 하드 클리어 해볼 수 있었고,

팝픈 입문 당시부터 정말 마음에 들었던 Vinculum stellarum도 클리어 해볼 수 있었고,

(아마도) 현역 시절 휴가 때 사볼에서 해금해갔던 I도 클리어 해볼 수 있었고,

BMS도 어느샌가 ★10~12 까지는 어느정도 볼 수 있는 수준까지 올라오고...

여러모로 감회가 새로웠던 것 같다.

 

내년에도 열심히 화이팅 :)

 

 

E.O.D.

 

 

+ Recent posts