---
title: "LMUL: 원소를 더 담으면 임시 레지스터가 줄어드는 이유"
author: "브레이브브라우저쓰자"
published_at: "2026-10-17T01:41:04.690Z"
updated_at: "2026-10-06T00:48:33.204Z"
tags: ["lmul"]
canonical_url: "https://ariser.io/@writer_a9817d5a8de0/lmul-%EC%9B%90%EC%86%8C%EB%A5%BC-%EB%8D%94-%EB%8B%B4%EC%9C%BC%EB%A9%B4-%EC%9E%84%EC%8B%9C-%EB%A0%88%EC%A7%80%EC%8A%A4%ED%84%B0%EA%B0%80-%EC%A4%84%EC%96%B4%EB%93%9C%EB%8A%94-%EC%9D%B4%EC%9C%A0"
ai_assisted: true
---

# LMUL: 원소를 더 담으면 임시 레지스터가 줄어드는 이유

이 글은 AI가 활용됐습니다.

[원문](https://ariser.io/@writer_a9817d5a8de0/lmul-%EC%9B%90%EC%86%8C%EB%A5%BC-%EB%8D%94-%EB%8B%B4%EC%9C%BC%EB%A9%B4-%EC%9E%84%EC%8B%9C-%EB%A0%88%EC%A7%80%EC%8A%A4%ED%84%B0%EA%B0%80-%EC%A4%84%EC%96%B4%EB%93%9C%EB%8A%94-%EC%9D%B4%EC%9C%A0)

벡터 원소를 더 많이 처리하려고 LMUL을 키웠는데, 사용할 수 있는 임시 레지스터가 급격히 줄었다. 이후 widening 연산까지 넣으니 아예 허용되지 않는 레지스터 그룹이 생겼다. LMUL은 계산기 개수를 늘리는 버튼이 아니라, 벡터 레지스터 이름을 묶는 설정이기 때문이다.

## 한 명령의 최대 원소 수를 계산한다

RISC-V 벡터에서 VLEN은 레지스터 한 개의 비트 길이, SEW는 설정한 원소 폭이다. 정수 LMUL=2,4,8은 각각 그 수만큼의 레지스터를 한 그룹으로 묶는다. 이때 최대 원소 수는 다음과 같다.

```text
VLMAX = LMUL × VLEN / SEW
```

설명용 구현의 VLEN을 256비트로 놓으면 다음 표를 얻는다. 각 설정과 연산의 지원을 전제로 한다.

| SEW | LMUL | 그룹의 비트 수 | VLMAX |
|---|---|---|---|
| 32 | 1 | 256 | 8 |
| 32 | 2 | 512 | 16 |
| 32 | 4 | 1024 | 32 |
| 64 | 2 | 512 | 8 |

SEW만 두 배로 바꾸면 같은 공간에 들어가는 원소는 절반이다. 반대로 LMUL을 함께 두 배로 키우면 원소 수를 유지할 수 있다. 하지만 물리 레지스터 한 개의 VLEN이 바뀐 것은 아니다. 여러 레지스터를 한 피연산자로 읽게 된 것이다. [RISC-V Vector, Vector Register Grouping](https://github.com/riscv/riscv-isa-manual/blob/main/src/unpriv/vector-common.adoc)

32개의 벡터 레지스터를 겹치지 않는 전체 그룹으로 나눌 때 LMUL=1에서는 32그룹, 2에서는 16그룹, 4에서는 8그룹, 8에서는 4그룹이다. 이는 mask나 다른 연산의 제약을 넣기 전의 이름 배분이다. 한 그룹이 커질수록 여러 입력과 임시 결과를 동시에 보관할 공간은 더 빨리 줄어든다.

## widening의 목적지는 두 배의 그룹을 요구한다

SEW=32, LMUL=4에서 32비트 입력을 더해 64비트 결과를 만드는 widening add를 생각해 보자. 입력 그룹은 4개 레지스터에 최대 32원소를 담는다. 같은 32원소를 64비트로 저장하려면 결과에 2048비트, 즉 8개 레지스터가 필요하다.

원문은 각 피연산자의 실제 그룹 배율을 EMUL로 구분한다. 이 widening에서 입력 EMUL은 4, 목적지 EMUL은 8이다. 예를 들어 입력을 v8~v11과 v12~v15에 두고 결과를 v16~v23에 쓰면 세 그룹이 겹치지 않는다. v8과 v12는 4개 그룹의 시작 조건을, v16은 8개 그룹의 시작 조건을 만족한다. [RISC-V Vector, Vector Operands](https://github.com/riscv/riscv-isa-manual/blob/main/src/unpriv/vector-common.adoc)

목적지를 v12로 옮기는 것은 단순히 겹침만 따질 문제가 아니다. 8개 그룹은 8의 배수 번호에서 시작해야 하므로, v12를 8개 그룹의 시작으로 쓰는 encoding은 reserved다. 소프트웨어가 “지금 vl이 작으니 실제로 두 레지스터만 쓰겠다”고 주장해도 이 그룹 지정 조건이 사라지지 않는다.

같은 widening을 LMUL=8에서 하면 목적지 EMUL은 16이 된다. 규약은 한 명령에서 사용하는 그룹이 8개 레지스터를 넘는 encoding을 reserved로 둔다. vl=1로 설정해 실제 계산 원소를 하나로 줄여도 이 명령의 그룹 요구를 허용되는 것으로 바꾸지는 못한다.

## 모든 겹침을 금지하면 규약보다 좁아진다

반대로 “목적지와 입력은 언제나 분리해야 한다”는 규칙도 정확하지 않다. 원문에는 폭과 그룹 위치에 따른 겹침 허용 조건이 있다. 목적지가 더 넓은 경우에는 입력 EMUL이 1 이상이고, 겹친 입력 그룹과 목적지 그룹의 가장 높은 레지스터 번호가 같아야 한다.

위 e32,m4 widening의 목적지를 v8~v15로 두고, 한 입력을 v12~v15로 두는 경우는 이 조건에 맞는다. 둘의 가장 높은 번호가 v15이기 때문이다. 다른 입력을 v16~v19에 두면 그 입력은 겹치지 않는다. 반면 목적지 v8~v15와 입력 v8~v11을 겹치게 하면 가장 높은 번호가 달라 이 조건을 만족하지 못한다. 더 좁은 목적지와 같은 폭의 경우에는 다른 허용 규정이 적용된다. [RISC-V Vector, register group overlap constraints](https://github.com/riscv/riscv-isa-manual/blob/main/src/unpriv/vector-common.adoc)

이 조건은 구현의 복구 가능한 예외 처리와도 연결된다. 겹침 여부만 보거나 시작 번호만 맞추는 검사는 부족하며, 각 피연산자의 폭과 EMUL을 함께 읽어야 한다.

## fractional LMUL은 레지스터 이름을 늘리지 않는다

LMUL=1/2처럼 작은 배율도 있다. VLEN=256, ELEN=64인 지원 구현에서 SEW=16, LMUL=1/2를 쓰면 그룹은 레지스터 하나의 절반인 128비트에 최대 8원소를 담는다. 서로 다른 짧은 값을 32개의 이름에 따로 두면서, 더 넓은 중간 결과가 여러 레지스터를 요구하는 부담을 줄일 수 있다.

그렇다고 나머지 절반에 새 이름이 생겨 64개 레지스터를 할당하는 것은 아니다. 여전히 이름은 v0~v31이며, 사용하지 않는 부분이 남는다. 지원 가능한 원소 폭도 fractional LMUL과 ELEN 등의 조건에 묶이므로 원하는 조합을 모두 쓸 수 있다고 가정해서는 안 된다.

LMUL을 고를 때의 질문은 “몇 배 빠른가”보다 “이 원소 폭과 연산에서 각 그룹이 몇 개의 이름을 차지하는가”에 가깝다. 큰 LMUL은 한 명령의 최대 작업량을 늘릴 수 있지만 lane 수나 실제 vl을 보장하지 않는다. 입력과 widening 결과의 EMUL, 그룹 정렬과 겹침, 남겨 둘 임시 공간까지 계산해야 늘린 용량을 올바른 코드로 사용할 수 있다.

