그들은 더 잘 알았어야 했다 — RISC-V 설계를 향한 신랄한 비판
그들은 더 잘 알았어야 했다 — RISC-V 설계를 향한 신랄한 비판
개방형 표준이라는 성취가 곧 좋은 설계를 보장하는가, 아니면 “누구나 만들 수 있다”는 자유와 “잘 만들었다”는 품질은 처음부터 서로 다른 축이었는가? 로열티 없는 명령어 집합이라는 이상은, 그 이상이 낳은 설계의 결함까지 면제해 주지는 않는다.
도입
RISC-V(리스크 파이브)는 최근 몇 년간 반도체 업계에서 가장 자주 회자된 이름 가운데 하나다. 로열티가 없는 개방형 명령어 집합 구조(ISA)라는 기치 아래, 스타트업부터 국가 주도 프로젝트까지 저마다 “다음 세대의 표준”을 자처하며 몰려들었다. 그런데 로우레벨 소프트웨어와 하드웨어 리버스 엔지니어링으로 이름난 엔지니어 Dmitry Grinberg가 「RISC-V: They Should Have Known Better(그들은 더 잘 알았어야 했다)」라는 도발적 제목의 장문 비판을 공개하며 이 낙관에 정면으로 찬물을 끼얹었다. 그의 논지는 뜻밖에도 단순하다. RISC-V가 망했다는 것이 아니라, 수십 년치의 선행 사례 — ARM, x86, MIPS — 가 눈앞에 펼쳐져 있었는데도 충분히 피할 수 있었던 실수를 되풀이했다는 것이다. Hacker News에 걸린 이 글은 451개의 댓글을 불러 모으며, RISC-V 지지자와 회의론자가 정면으로 충돌하는 장이 되었다. 흥미로운 것은 대립의 성격이다. 한쪽은 명령어 인코딩의 세부까지 파고들며 “설계가 게으르다”고 말하고, 다른 쪽은 “개방성과 채택 모멘텀이 세부의 흠결을 압도한다”고 답한다. 이 글은 그 비판의 구체적 항목들을 검증 가능한 스펙 사실과 저자의 의견으로 갈라 정리하고, 반론까지 나란히 놓아 “개방형 표준”이라는 성취가 곧 “좋은 설계”를 뜻하는지 되묻는다.
무엇을 비판하는가: 압축 명령부터 인터럽트까지
먼저 Grinberg가 짚은 구체적 설계 결정들을 사실 층위에서 정리하자. 여기서 “사실”이란 RISC-V 스펙 문서에 명시된 인코딩·확장의 구성 자체를 말하고, 그 위에 얹힌 수치·평가는 저자의 분석과 의견으로 따로 구분한다.
첫째는 인터럽트 처리다. RISC-V의 기본 정수 코어에는 인터럽트 진입 시 자동으로 레지스터를 보관해 주는 하드웨어가 없고, MIPS의 $k0/$k1처럼 커널이 마음대로 쓸 수 있게 예약된 레지스터도 없다. 그래서 인터럽트 핸들러는 CSRRW 계열 명령으로 레지스터를 손수 대피시켰다가 다시 복원해야 한다. 저자는 이 경로를 실제로 세어, Cortex-M0가 27사이클에 끝내는 인터럽트 진입/복귀를 RISC-V는 최소 44사이클에 한다고 주장한다(레지스터 저장 21사이클, 복원 20사이클에 JAL/RET 오버헤드가 더 붙는다는 계산이다). 여기서 “CSR을 통한 우회가 필요하다”는 것은 스펙에서 확인되는 사실이고, “27 대 44사이클”은 그가 특정 조건에서 산출한 측정값이라는 점을 구분해 둘 필요가 있다.
둘째는 압축 명령(C 확장)의 인코딩이다. 압축 명령은 명령어를 16비트로 줄여 코드 밀도를 높이는 장치인데, 저자가 보기에 그 설계가 어설프다. 압축된 바이트 저장 명령은 오프셋을 03바이트밖에 지원하지 않고(ARM은 같은 자리에서 031을 쓴다), 하프워드 저장은 0~2바이트에 비트 제약까지 임의적이다. 게다가 정작 밀도에 도움이 될 법한 명령들은 선택적 Zcb 확장으로 밀려나 있어, “밀도를 위한 확장”이라는 명분이 무색해진다.
셋째는 없는 명령과 없는 주소 지정 방식이다. RISC-V 기본 ISA에는 비트를 검사해 분기하는 test-bit-and-branch(ARM의 TBZ/TBNZ)가 없고, 비트필드 삽입·추출도 기본에는 없다. 저자는 aarch64로 빌드된 Linux 커널 바이너리를 분석해 TBZ/TBNZ가 35,393회, 비트필드 삽입이 6,284회, 비트필드 추출이 8,881회 쓰였다고 집계했다 — 즉 결코 희귀한 명령이 아니라는 것이다. RISC-V에서 배열 인덱싱을 돕는 SHxADD(Zba 확장)는 스펙이 나온 지 2년이 지나서야 추가됐고, 그마저도 ARM이 4바이트로 하는 일을 6~8바이트 명령열로 처리한다. 여기서 “기본 ISA에 해당 명령이 없다”와 “Zba가 나중에 추가됐다”는 검증 가능한 사실이고, 커널 바이너리의 사용 횟수는 저자가 특정 바이너리에서 센 값이다. 그가 “배열이 존재한다는 걸 깨닫는 데 2년이 걸렸다”고 비꼰 대목은 명백히 그의 의견이다.
넷째는 즉치값(immediate) 인코딩이다. RISC-V는 명령어 안에 박히는 상수의 비트들을 순서대로 두지 않고 흩뿌려 놓는다. 예컨대 J형 즉치값의 비트 순서는 20·10·9·8·7·6·5·4·3·2·1·11·19·18·17·16·15·14·13·12이고, 압축 분기 C.J는 또 다른 뒤섞인 순서를 쓴다. 명령 형식(I/S/B)마다 즉치값을 뽑아내는 위치가 제각각이고, 압축 명령에는 9가지가 넘는 인코딩 포맷이 있다. 스펙의 공식 해명은 “같은 비트를 늘 같은 자리에서 뽑으면 하드웨어가 단순해진다”는 것인데, 저자는 이를 “어리석다(idiotic)“고 일축한다. 하드웨어의 멀티플렉서에게 비트 순서란 그저 배선일 뿐, 순서가 뒤섞였다고 게이트가 늘지 않는다는 것이다. 인코딩 자체는 사실이고, “어리석다”는 판정은 그의 의견이다.
왜 이렇게 됐는가: 선택성, 파편화, 그리고 자기를 감지할 수 없는 표준
개별 흠결을 넘어 저자가 진짜 겨누는 것은 RISC-V의 설계 철학, 특히 “극단적 선택성”이다. RISC-V에서는 곱셈·나눗셈(M 확장), 압축 명령(C), CSR 접근(Zicsr), 심지어 유저/슈퍼바이저 모드까지 상당수가 선택적이다. 저자의 핵심 명제는 이것이다 — “무언가를 선택적으로 만들 때마다, 당신은 가능한 구현들을 서로 호환되지 않는 두 무리로 쪼갠다.” 하나의 커널이 여러 코어에서 돌게 하려면 어떤 기능이 있는지 알아야 하는데, RISC-V에서는 그것을 알아내는 일 자체가 함정에 빠진다.
가장 인상적인 역설은 기능 감지다. RISC-V에서 어떤 확장이 구현됐는지 알려 주는 레지스터 MISA는 그 자체가 CSR이다. 즉 CSR이 있는지 알려면 CSR을 읽어야 하는데, CSR 지원 자체가 선택적이다. 게다가 MISA는 머신 모드에서만 보이고, 슈퍼바이저·유저 코드에는 보이지 않으며, 구현이 이 레지스터를 몽땅 0으로 읽어도 스펙 위반이 아니다. x86의 CPUID나 ARM의 기능 레지스터가 당연하게 해결하는 문제를, RISC-V는 원리적으로 해결하지 못하게 만들어 놓은 셈이다. 여기에 더해 저자는 인코딩 충돌도 짚는다. 같은 16비트 값 0xA002가 D 확장이 있으면 C.FSDSP(부동소수점 저장)를, Zcmp 확장이 있으면 CM.JT(점프 테이블)를 뜻한다. 0xAC66 역시 확장 조합에 따라 전혀 다른 명령이 된다. 그의 표현으로 “프로세서를 업그레이드했더니 멀쩡하던 바이너리가 의미가 다른 멀쩡한 바이너리로 바뀌는” 일이 벌어진다. x86은 인코딩이 아무리 지저분해도 50년간 이 의미적 안정성만은 지켰다는 게 그의 대비점이다.
파편화를 봉합하려고 만든 장치조차 파편화를 낳는다는 지적도 있다. RISC-V 재단은 특정 용도에 필요한 확장 조합을 묶은 “프로파일”(RVA23 등)을 도입했는데, 저자가 세어 보니 시중의 보드 대부분이 RVA23을 만족하지 못한다. VisionFive 2, Banana Pi BPI-F3, Lichee Pi 4A, Orange Pi RV2, HiFive Premier P550 모두 비준수였고, 준수 사례로 언급된 것은 SpacemiT K3 정도였다. 결국 시장은 “거의 RVA23”과 “RVA23 이후”로 다시 갈라지고, Android와 Linux가 비준수 하드웨어를 버리는 결말이 온다는 것이다. 그는 “파편화를 풀려고 만든 프로파일이 RISC-V 세계를 파편화한다”고 요약한다. 이 모든 실수의 뿌리로 그는 “여기서 만들지 않은 것(Not Invented Here)” 증후군을 지목한다. 지연 슬롯도 없이 이미 존재하던 OpenRISC를 개선하는 대신 백지에서 다시 시작하기로 한 결정이, 흩뿌려진 비트 인코딩과 충돌하는 확장과 빠진 명령들을 낳았다는 논리다.
물론 반론도 만만치 않았다. HN 토론에서는 프로파일이야말로 파편화의 해법이라는 옹호가 나왔다 — RVA23 같은 프로파일이 용도별 확장 조합을 표준화하므로, 프로파일을 겨냥한 소프트웨어는 어떤 기능이 있는지 정확히 안다는 것이다. “감지할 방법이 없다”는 주장은 과장이라는 지적도 있었다. Linux의 디바이스 트리 블롭과 misa 레지스터가 실제 배포 시나리오에서는 확장 발견을 충분히 해낸다는 반박이다. 흩어진 즉치값 인코딩에 대해서도, 그것이 게으름이 아니라 커스텀 벤더 확장을 위한 인코딩 공간을 미래 충돌 없이 남겨 두려는 의도적 선택이라는 설명이 나왔고, 한 참여자는 실제로 세 곳에서 뽑히는 비트는 단 1개뿐이라 멀티플렉서 복잡도가 감당할 만하다는 통계를 제시했다. x86을 이상화하지 말라는 목소리도 있었다 — AVX-512의 파편화, SSE4.x 대 SSE4a의 충돌, Intel과 AMD의 가상화 비호환을 들어, RISC-V의 확장 모델만 유별나게 나쁜 것은 아니라는 균형론이다. 코드 밀도 논쟁에서는, AArch64가 복잡한 명령을 여러 마이크로연산으로 “크래킹”해 밀도를 얻는 반면 RISC-V는 가변 길이 인코딩으로 얻으며, 양쪽 다 프런트엔드 비용을 치른다는 정리가 나왔다. 다만 옹호론자들조차 “확장 감지가 x86의 CPUID만큼 매끄럽지는 않다”는 점은 대체로 인정하는 분위기였다.
개방성은 품질이 아니다: 전망과 실무적 시사점
이 논쟁의 밑바닥에는 한 문장이 있다. 저자가 거듭 강조하듯, 개방된 명세가 좋은 구현을 공짜로 낳아 주지는 않는다. ARM의 폐쇄적·독점적 설계가 RISC-V를 앞서는 것은 라이선스료 때문이 아니라 설계 결정이 더 낫기 때문이며, 따라서 “RISC-V 스펙이 개방됐다”는 사실은 성능과 무관하다는 것이다. 이것은 오픈소스 문화가 오래 품어 온 은근한 등식 — 개방적인 것은 곧 우월하다 — 을 정면으로 부정한다. 개방성은 접근성과 통제권의 축이고, 설계 품질은 별개의 축이라는 냉정한 분리다.
그렇다면 RISC-V는 어디서 이기고 어디서 질까. 저자의 전망은 의외로 구체적이다. RISC-V는 값싼 단발성 마이크로컨트롤러 시장 — 오래된 8051을 밀어내는 자리 — 을 결국 장악할 것이다. 단 ISA가 뛰어나서가 아니라, ISA에도 불구하고, 오로지 값이 싸기 때문이다. 또한 머신러닝 가속기의 제어부(연산이 아니라 DMA 설정 같은 살림살이)나 넓은 벡터 보조 프로세서의 컨트롤러처럼, 정수 파이프라인의 효율이 병목이 아닌 자리에서도 잘 쓰일 것이다. 반대로 게임·브라우징 같은 데스크톱·SBC의 대화형 컴퓨팅과 고성능 컴퓨팅에서는, 마케팅 구호와 달리 아웃오브오더 코어에 잘 맞지 않아 고전하리라는 예측이다. 그의 촌평은 이렇게 압축된다 — “‘충분히 좋음’은 이 경우 낮은 기준이고, RISC-V는 딱 그 기준에 맞는 키다.” 다시 강조하지만 이 시장 예측은 검증된 사실이 아니라 저자의 판단이며, 채택 모멘텀과 생태계 락인이 설계 흠결을 어느 정도까지 상쇄할지는 열려 있는 질문이다.
실무 엔지니어에게 이 논쟁은 추상적 취향 다툼이 아니다. RISC-V를 겨냥해 이식성 있는 저수준 코드나 커널을 쓰려는 사람이라면, “어떤 확장이 있는지 실행 시점에 안전하게 알아낼 수 있는가”라는 물음이 실제 제약으로 돌아온다. 프로파일(RVA23)을 타깃으로 삼으면 상당 부분 해소되지만, 시중 하드웨어가 그 프로파일을 만족하지 못하는 과도기에는 “거의 준수” 보드를 위한 예외 처리가 코드를 갉아먹는다. 낙관 시나리오는 프로파일이 빠르게 확산돼 사실상의 공통 기준선이 서고, 컴파일러·배포판이 그 위에서 안정되는 것이다. 비관 시나리오는 벤더별 커스텀 확장이 난립해 “RISC-V 호환”이라는 말이 실질을 잃는 것이다. 현실은 그 사이 어딘가 — 프로파일이 서서히 표준을 조여 가되, 저가 임베디드에서는 여전히 제각각인 코어들이 공존하는 모습일 공산이 크다. 요점은 하나다. RISC-V로 간다는 결정은 “하나의 CPU”가 아니라 “확장의 스펙트럼”을 상대하겠다는 결정이며, 그 스펙트럼의 어느 지점을 지원할지를 먼저 못 박아야 한다.
결론
리드의 질문으로 돌아가자. 개방형 표준이라는 성취는 곧 좋은 설계를 뜻하는가. Grinberg의 답은 단호한 “아니오”다. 그리고 이 지점에서 그의 비판은 단순한 트집을 넘어선다. 개방성은 누구나 만들 수 있게 하는 힘이지, 잘 만들도록 강제하는 힘이 아니다. 흩뿌려진 즉치값, 자기를 감지하지 못하는 MISA, 업그레이드가 바이너리의 의미를 바꾸는 인코딩 충돌 — 이것들은 라이선스가 자유롭다고 사라지는 문제가 아니다. 오히려 자유롭게 확장할 수 있기에 더 쉽게 갈라지는 문제다.
그러나 저자의 비판을 인정하는 것과 RISC-V를 단념하는 것은 다른 이야기다. 반론들이 상기시키듯, x86과 ARM도 각자의 지저분함을 안고 시장을 지배했고, 살아 있는 표준은 프로파일과 확장으로 사후에 흠결을 메울 여지가 있다 — 이미 고정된 ISA가 더는 고칠 수 없는 실수를 안고 굳어 가는 것과 대조적으로. 결국 남는 질문은 엔지니어 각자의 몫이다. 당신이 다음 프로젝트에서 RISC-V를 고른다면, 그것은 설계가 우아해서인가, 아니면 값이 싸고 로열티가 없어서인가? 그 두 이유를 스스로에게 정직하게 구분하는 것이, “개방형”이라는 단어에 설계 품질까지 슬쩍 얹어 주지 않는 첫걸음이다.
출처: