복학 첫 학기를 마치며: 2024-2학기 회고

Dec. 8, 2024, 4:01 p.m. · 6 min read · 🌐︎ ko


눈 내린 학교

칼복학을 하다

2023년 3월에 군대를 갔던 나는 정확히 올해 9월 5일에 전역을 했다. 여유롭게 한 학기를 더 쉬다가 학교로 돌아가는 선택지도 있었지만, 주변의 많은 만류에도 불구하고 나는 말년휴가를 써서 "칼복학"을 하는 것을 선택하게 됐다. 몇 가지 이유가 있었다.

우선 태어나서 거의 처음으로 1년 반동안 학업이 완전히 끊기면서, 함께 공부하던 친구들이 전부 앞서나가는 것을 보고만 있는게 그리 유쾌한 경험은 아니었다. 또 군대에서 혼자 독학으로 조금씩 공부를 하면서, 혼자 공부하는 것의 한계를 느끼고 학교에서 수업을 듣고 싶다는 갈증이 많이 생겼던 것 같다. 심지어는 학기 중의 성적에 대한 부담이나 압박 마저도 조금은 그리웠다. 결국 어느 정도의 pressure는 있어야 제대로 배우는 법이니까.

아무튼 그렇게 기다리던 복학을 하고, 이전처럼 다시 수업과 과제에 치여 정신없이 지내다보니 어느새 한 학기가 모두 끝났다. 이번 학기는 고등학교 때를 포함해 가장 바쁘게 보냈었던, 또 가장 많은 것을 배웠던 학기 중 하나가 아니었다 싶다. 이번 학기에 들었던 전공과목들과 각각에서 배운 것들을 정리해보고자 한다.


이번 학기 시간표

컴퓨터 조직론

이번학기에 들었던 과목중 제일 많이 배웠던 과목이 아니었을까 싶다. 아니, 아마 순수 학습량으로는 대학교에 와서 들었던 모든 과목 중에서 1등일 것 같다.

처음 몇 주동안은 pipelined CPU를 배우기 위한 빌드업을 거쳐 superscalar와 out-of-order execution, multicore processor까지를 배우고 중간고사를 쳤다. 기말고사 범위로는 cache와 memory hierarchy, cache coherence와 memory consistency, interconnection network를 배운 후에 간단하게 GPU도 다루고 끝났다.

우선 저 내용을 전부 다 한 학기에, 그것도 3학점으로 배운다는 것 자체만으로도 부담이 큰 편이었다. 슬라이드에서는 아주 잠깐만 설명한 부분도 시험에는 다 나왔기 때문에 수업이 끝나고 복습하는 데 시간을 굉장히 많이 할애해야 했다. 나는 사실 평소에 수업을 그렇게 집중해서 듣는 편이 아니었는데 이 과목만큼은 매 시간 정말 최대한 집중력을 끌어모아서 들었던 기억이 있다. 나같은 경우는 군대에서 Coursera에 올라와 있는 프린스턴 대학교 아키텍처 강의를 미리 예습해둔게 많이 도움이 되긴 했다. 그 때는 '대충 이런게 있구나' 하는 식으로 넘어갔다가 이번 학기 수업을 듣고서야 제대로 이해한 것들이 대부분이었긴 하지만, 어쨌든 큰 그림을 하나 가지고 수업을 들어갔던건 도움이 많이 됐던 것 같다. 아니었으면 이렇게 다른 전공 과목을 3개씩 같이 병행하기는 힘들었을지도 모른다.

또 수업 외에도 베릴로그 랩 과제가 있었는데 여기에도 꽤 시간과 노력을 많이 투자해야 했다. Single cycle과 multi-cycle CPU에서 시작해서 pipelining과 branch prediction, cache, DMA 기능까지 있는 CPU를 차근차근 구현해나가는 과제가 2주에 한 번 정도 있었는데, 코드 자체가 엄청나게 길고 복잡하지는 않았지만 디버깅에 시간을 꽤 많이 쏟아야 했다. 예를 들어서 branch misprediction과 data hazard, d-cache miss가 동시에 발생한다면 pipeline의 어느 단계를 stall하고 어느 단계를 진행시킬 지 제대로 고민해보지 않았더라면 디버깅을 통해 수정하기는 굉장히 힘들다. 이런 부분을 미리 생각한 후에 구현에 들어갔어야 했는데 막무가내로 코드부터 짜고 시작하다보니 꽤 시간이 많이 걸렸던 것 같다. 그래도 결과적으로는 pipeline에 이틀, cache에 사흘 정도를 쓴걸 빼면 전부 하루만에 끝내긴 했다. Forwarding logic을 구현하는 것 등이 추가과제로 나왔었는데, 다른 과목 과제 하느라 못했던게 좀 아쉽다. 그래도 이걸 하면서 verilog를 할 줄은 안다고 말할 수 있게 되지 않았나 싶다.


All pass!

아무튼 힘들었지만, 그만큼 정말 많이 배울 수 있었던 시간이었고 또 아키텍처에 흥미를 갖게 해준 과목이었다. 열심히 했던만큼 중간은 1등, 기말은 최고점을 공개해주시지는 않아서 모르겠지만 만점에 가까운 점수를 받았는데, 그동안 떨어져있던 공부에 대한 자신감을 많이 회복시켜준 과목이기도 하다.

확장형 고성능 컴퓨팅

컴퓨터조직론에 이어서 이번 학기 두 번째로 많은 시간을 쓴 과목이다. 처음으로 들은 대학원 과목이기도 하다. 과목명을 영어로 하면 scalable high-performance computing인데, 쉽게 말하면 병렬 프로그래밍을 배우는 과목이다. 수업 초반 몇 주 동안은 시스템 프로그래밍, 운영체제 등에서 배우는 내용들을 간단히 복습하고, 이후부터 본격적으로 pthread, OpenMP, OpenCL, CUDA, MPI 등 라이브러리 사용법을 배웠다. 마지막에는 DeepSpeed ZeRO도 배웠다.

확고컴은 수업 내용도 좋았지만 학기말 프로젝트에서 정말 많이 배운 과목이었다. 프로젝트는 CNN 기반 자연어처리 모델을 NVIDIA GPU 16개로 이루어진 클러스터에서 돌아가도록 최적화하는거였는데, 정말 대학을 와서 지금까지 했던 과제 중에 제일 재밌었던 경험이었다. 다만 프로젝트를 하는 과정에서 정말 많이 헤매긴 했다. 우선 평가가 무려 "4등의 점수를 기준으로 throughput이 2배 떨어질 때마다 10점씩 감점"하는 상대평가 방식이었다. 나는 GPU 프로그래밍을 처음 해보는 입장이었고, 더군다나 중간고사를 좀 못쳤어서1 프로젝트를 잘 해야 한다는 부담감이 꽤 심했던 것 같다. 그래서 거의 공지되자마자 프로젝트를 시작해서 한 달이 넘게 프로젝트에 매달렸는데, 수업에서 GPU 아키텍처를 제대로 배우지 않은 상태에서 맨 땅에 헤딩하듯 시작하다보니 혼자 정말 많이 헤맸었다. 예를 들어서 Shared memory의 bank conflict나 coalesced memory access 등의 개념을 모르는 상태로 성능 최적화를 하려니 잘 돼도 왜 되는지를 모르고, 잘 안돼도 그 이유를 모르는 것이다. 차라리 프로젝트를 좀 더 늦게 시작하거나, 수업에서 진도를 나가지 않았어도 개인적으로라도 공부를 좀 하고 착수했으면 훨씬 시간을 많이 절약할 수 있지 않았을까 하는 아쉬움은 있다. 어쨌거나 batching과 kernel fusion, Im2Col2 등을 적용해보고, 행렬곱은 tensor core를 사용해서 하도록 하니 최종 성능은 117666 sentences/sec이 나왔다. CPU에서 돌아가는 baseline code 성능이 0.76이었으니 약 15만 배 빠른 셈이다.

결과적으로는 4등 안에 들어서 100점을 받았다!(자랑) 정말 정말 많은 시간을 투자하고 많은 공을 들여서 해낸 프로젝트다보니, 이번 학기 제일 기분 좋았던 기억으로 남아있다. 힘들긴 했지만 하나씩 아이디어를 내서, 한나절씩을 꼬박 들여서 구현과 디버깅을 거쳐 적용한 최적화가 진짜로 좋은 성능을 낼 때는 정말 짜릿하고 재밌었던 것 같다. GPU 16개를 써서 최적화하는 경험을 해볼 수 있다는 것 자체만으로도 이 과목을 들을 이유는 충분했다고 생각한다.

컴퓨터 시스템 프로그래밍

CS:APP를 교재로 수업한 시스템 프로그래밍 수업이다. CS:APP 교재를 기반으로, 컴조 등 다른 과목과 너무 겹치는 부분은 제외하고 진도를 나갔다. 과제는 트리 정렬을 assembly로 구현해보는 과제와 C언어 malloc 함수를 직접 구현해보는 malloc lab, x86의 int 3 instruction을 이용해 debugger를 구현해보는 snudbg, tsh라는 간단한 unix shell을 구현해보는 shell lab이 있었다. 또 교수님이 보안 전공이신만큼 각 챕터에서 배운 내용과 관련된 CTF(capture-the-flag)과제가 총 7개 나왔다.

나의 경우 사실 2년 전에 들었다 드랍했었는데, 그 때와 달리 군대에서 CS:APP를 한번 예습한 후 듣기도 했고 컴조/확고컴과 같이 들으니 수업 내용은 거의 아는 내용이 많아 큰 부담은 없었던 것 같다. 다만 과제에서는 정말 많이 배울 수 있었다. malloc lab, debugger lab을 하면서 system level에서의 C언어 프로그래밍을 해보는 것 또한 굉장히 재밌었던 경험이었다. 특히 malloc은 utilization을 올릴수록 추가 점수가 있었는데, 어떻게 해야 fragmentation을 줄일 수 있을지 고민해보고 아이디어를 구현해보며 테스트해보는 과정도 되게 재밌었다. Shell lab도 직접 해보지 않았다면 signal이나 redirection 등을 피상적이고 개념적인 수준에서만 이해할 수 있었을 것 같은데, 적절하게 나와서 제대로 된 이해에 도움을 많이 준 것 같다. CTF도 코드의 취약점을 어떻게 exploit할지 고민해보는게 되게 재밌었고 흥미로웠다. 그런 퀄리티의 과제들을 조교님들이 직접 만드셨다는게 그저 너무 대단하다.

시험은 기말고사만 쳤는데, 개인적으로는 시험 자체의 재미로는 대학교 와서 친 시험중에 가장 재밌었던 것 같다. Return-oriented programming으로 exploit 코드를 직접 작성하는 문제부터 linking 전후의 binary code를 추측해서 써보는 문제 등이 나왔는데 문제가 다들 흥미로워서 좋았다. 시험 준비에는 CMU Introduction to Computer Systems 기출문제를 풀어본게 도움이 많이 된 것 같다. 사실 다른 과목들 때문에 시험 준비에 시간을 많이 쓰지는 못했는데, 예전에 CS:APP를 한번 정독했던 덕분에 시험은 잘 볼 수 있었다.

제어공학개론

State-space model에서 시작해 observability/controllability, feedback controller와 observer, LQR 등을 배웠다. 특이하게도 고전제어는 수업 후반부에 와서야 다뤘는데, Root-locus plot과 Nyquist stability criterion 등을 배웠다. 또 Matlab을 써서 수업시간에 배운 제어 기법들을 시뮬레이션해보는 과제가 네 차례 나왔었다.


한 학기 내내 하던 three-cart system

나머지 전공 세 과목이 전부 시스템 분야 과목인지라 수학을 쓰는 과목도 하나 듣고 싶다는 생각에 신청했었던 과목이다. 입대 전 항상 수학만큼은 자신있었기도 하고, 과제도 거의 없는 편이라고 해서 상대적으로 수월하게 학점을 받을 수 있지 않을까 하는 생각도 있었다.

그런데 제어공학개론은 생각보다는 만만한 과목은 아니었다. 우선 1년 반동안 적분 한번 제대로 해본 적 없는 나에게 숫자에 대한 감이 다시 돌아오기까지는 꽤나 많은 시간이 걸렸다. 행렬로 가득한 연습문제들을 오랜만에 풀어보려 하니, 거의 한 줄 한 줄 식을 전개해 나갈 때마다 실수가 하나씩 생겼다. 확 떨어진 수학 실력을 체감하고서, 중간고사 기간에는 거의 공학수학 연습문제나 풀면서 공부했었다. 그런데도 실제 시험장에 가보니 계속 실수가 나왔고, 시험장을 나설 때는 잘 쳤다고 생각했던 시험이었지만 결과는 그리 좋지는 않았다.

하지만 본격적으로 제어 이론들을 배우기 시작하니 수업이 조금은 더 재밌어졌던 것 같다. 또 공부할 교재가 없어 애를 좀 먹었다가 수업이랑 비슷하게 진도를 나가는 Linear State-Space Control System이라는 책을 발견하고 이걸로 공부했던게 도움이 많이 됐었다. 중간을 잘 못본 걸 커버해야 한다는 생각에 기말고사 기간에는 거의 일주일동안 제어공학개론 공부만 했었는데, 그 때문에 다른 과목 공부가 많이 밀리긴 했지만 제공개 한 과목은 확실히 잡고 갈 수 있었던 것 같다. 덕분에 기말고사는 만점을 받을 수 있었다.

결과론적으로 보면 성적은 좋게 나올 것 같지만, 제어공학이 나에게 잘 맞다는 느낌을 받지는 못했었다. 교수님의 강의력은 정말 흠잡을 데가 없었고 수업 내용에서 흥미로웠던 내용도 많았지만 그 이상의 감흥은 없었던 것 같다. 다만 배우고 싶었던 state-space model을 제대로 배울 수 있었고, 수학을 쓰는 과목들에 대한 자신감도 회복할 수 있었다는 점에서 제공개를 수강한건 후회없는 선택이었다고 생각한다.


초등학교에 들어가서부터, 그렇게 오랫동안 학교도, 수업도 시험도 없던 기간은 군대가 처음이었다. 그런만큼 1년 반의 공백기를 가진 후 다시 시작된 학교생활은 참 낯설고 어색했다. 특히 첫 시험부터 결과가 좋지 않았다보니 계속 생기기만 하는 수업과 과제가 더욱 힘겹게만 느껴지기도 했다.

하지만 묵묵히 주어진 일들에 최선을 다하다보면 결국 좋은 결과는 따라오나 보다. 조금은 회의감과 의문도 들었었던 한 학기였지만, 어영부영 마치고 나서 생각해보니 결국 내가 있어야 할 곳은 학교밖에 없구나 싶다. 그래도 아직 나에게는 새로 뭔가를 배우면서 얻는 성취감이 가장 큰 기쁨 중 하나가 아닌가..하는 생각도 든다. 힘들지 않았다면 거짓말이지만, 정말 많이 배우고, 또 많이 성장할 수 있었던 한 학기였다!


  1. 약 1년 반만에 치는 시험이었어서.. 어쩌면 시험치는 방법을 까먹은게 아니었을까.. 

  2. convolution을 행렬 연산으로 바꿔서 수행하는 것