# 릴리즈 노트

## v1.4.0

**출시일:** 2026년 8월 21일
**유형:** Minor

NPU 관리 라이브러리 mbltml 출시, `mobilint-cli top` 모니터, 하나의 런타임 산출물로 모든 NPU 디바이스 지원, `NPUData`와 혼합 코어 모드 베타 지원이 포함되었습니다.

### 추가

- **[Highlight]** **mbltml — NPU 관리 라이브러리** — 시스템에 장착된 모든 모빌린트 NPU의 상태를 관찰하는 새 라이브러리입니다. 드라이버·펌웨어 버전, 온도, 클럭, 전력, 메모리 사용량, 사용률, 코어별 활동, 디바이스를 점유 중인 프로세스 정보를 조회할 수 있습니다. 배포 이름은 `mobilint-ml`이며, 버전은 qb Runtime과 동일하게 관리됩니다. 즉 mbltml v1.4가 qb Runtime v1.4와 짝을 이룹니다.

  ```bash
  pip install mobilint-ml         # PyPI
  sudo apt install mobilint-ml    # Debian, Ubuntu
  sudo dnf install mobilint-ml    # RHEL, Rocky Linux
  ```

  모듈 이름은 `mobilint-ml`이 아니라 `mbltml`입니다. Python에서는 `import mbltml`, C/C++에서는 `#include <mbltml/mbltml.h>`로 사용합니다. 디바이스 번호는 디바이스 종류별로 부여되므로(`aries-rb`와 `regulus-ra`가 모두 0번일 수 있습니다) 모든 조회 API는 타겟 디바이스 종류와 디바이스 번호를 함께 받습니다.

  ```cpp
  // C API 예시 (헤더는 C와 C++ 모두에서 사용 가능)
  #include <mbltml/mbltml.h>
  #include <stdio.h>

  int main() {
      if (mbltmlInit() != MBLTML_SUCCESS) {
          return 1;
      }

      unsigned int count = 0;
      mbltmlGetTargetDeviceCount(MBLTML_TARGET_DEVICE_ARIES_RB, &count);

      for (int dev_no = 0; dev_no < (int)count; ++dev_no) {
          int temperature = 0;
          double utilization = 0.0;
          mbltmlGetTemperature(MBLTML_TARGET_DEVICE_ARIES_RB, dev_no, &temperature);
          mbltmlGetTotalUtilization(MBLTML_TARGET_DEVICE_ARIES_RB, dev_no, &utilization);
          printf("aries-rb #%d: %d C, utilization %.2f\n", dev_no, temperature, utilization);
      }

      mbltmlShutdown();
      return 0;
  }
  ```

  ```python
  # Python 예시
  import mbltml

  mbltml.mbltmlInit()
  try:
      for dev_no in range(mbltml.mbltmlGetTargetDeviceCount(mbltml.MBLTML_TARGET_DEVICE_ARIES_RB)):
          temperature = mbltml.mbltmlGetTemperature(mbltml.MBLTML_TARGET_DEVICE_ARIES_RB, dev_no)
          utilization = mbltml.mbltmlGetTotalUtilization(mbltml.MBLTML_TARGET_DEVICE_ARIES_RB, dev_no)
          print(f"aries-rb #{dev_no}: {temperature} C, utilization {utilization:.2f}")
  finally:
      mbltml.mbltmlShutdown()
  ```

  - [mbltml C API 레퍼런스](../doxygen/html_kr_mbltml/group__MbltmlCAPI)
  - [mbltml Python API 레퍼런스](../doxygen/html_kr_mbltml/group__MbltmlPyAPI)

- **[Highlight]** **하나의 런타임 산출물로 모든 NPU 디바이스 지원** — 하나의 qb Runtime 산출물이 모든 타겟 디바이스를 지원합니다. {doxylink}`Accelerator <mobilint::Accelerator>`는 디바이스 번호와 함께 타겟 디바이스 이름 `"aries-rb"`, `"regulus-ra"`, `"regulus-rb"`, `"regulus-ra-usb"`, `"regulus-rb-usb"`를 받으며, 이름은 대소문자를 구분하지 않습니다.

  `"auto"`, `"aries"`, `"regulus"`, `"regulus-usb"`는 별칭으로 동작하여 실제 타겟 디바이스로 자동 해석되지만, 조건에 맞는 디바이스 종류가 시스템에 단 하나만 존재할 때에만 해석됩니다. 해석이 모호한 경우 임의로 선택하지 않고 실패하므로, 두 종류 이상의 NPU가 장착된 시스템에서는 디바이스 이름을 명시해야 합니다.

  ```cpp
  // C++ 예시
  mobilint::StatusCode sc;

  // 장착된 타겟 디바이스 이름과 각 디바이스 번호를 확인합니다.
  for (const auto& name : mobilint::getAvailableDevices()) {
      for (int dev_no : mobilint::getAvailableDeviceNumbers(name)) {
          printf("%s #%d\n", name.c_str(), dev_no);
      }
  }

  auto acc = mobilint::Accelerator::create("aries-rb", 0, sc);
  if (!sc) {
      fprintf(stderr, "Error code %d\n", int(sc));
      exit(1);
  }
  printf("opened %s\n", acc->getDeviceName().c_str());
  ```

  ```python
  # Python 예시
  for name in qbruntime.get_available_devices():
      print(name, qbruntime.get_available_device_numbers(name))

  acc = qbruntime.Accelerator("aries-rb", 0)
  print(acc.get_device_name())
  ```

  함께 추가된 API는 다음과 같습니다. `getAvailableDevices()`는 감지된 타겟 디바이스 이름 목록을, `getAvailableDeviceNumbers(device_name)`는 특정 이름 또는 별칭에 해당하는 디바이스 번호 목록을 반환하고, `Accelerator::getDeviceName()`은 별칭이 어떤 타겟 디바이스로 해석되었는지 알려줍니다.

- **`mobilint-cli top`** — 터미널에서 ARIES NPU 상태와 자원 사용량을 지속적으로 모니터링합니다. 유틸리티 패키지에 이미 포함되어 있던 `mobilint-ctrl-cli` 모니터를 그대로 실행하므로, 추가로 설치하거나 별도로 실행할 것이 없습니다. 현재는 REGULUS(SoC)용 `mobilint-cli` 빌드에는 이 명령이 포함되지 않습니다.

  ```bash
  mobilint-cli top
  ```

  `mobilint-cli` 명령 전체 목록은 [유틸리티 사용](utility_usage.md)을 참고하세요.

- **(베타) `NPUData`** — {doxylink}`NPUData <mobilint::NPUData>`는 모델의 입력 또는 출력 텐서 하나를 나타내는 객체로, 자신의 저장 공간을 소유하며 요청에 따라 호스트(CPU) 메모리와 NPU 메모리 사이를 이동합니다. 추론 데이터가 지금 어디에 있는지를 명시적으로 다룰 수 있어, 여러 NPU를 사용하거나 하나의 NPU에서 여러 모델이 텐서를 주고받는 경우에 유용합니다.

  launch된 모델에서 `acquireInputNPUData()` / `acquireOutputNPUData()`(Python은 `acquire_input_npu_data()` / `acquire_output_npu_data()`)로 획득하고, 호스트에 있는 동안 데이터를 채운 뒤 `launch()`로 가속기에 올려 추론합니다. 결과를 읽기 전에는 `cpu()`를 호출해 호스트로 다시 가져옵니다.

  ```cpp
  // C++ 예시
  mobilint::StatusCode sc;

  mobilint::NPUData in = model->acquireInputNPUData({224, 224, 3}, 0, false, sc);
  float* host = in.data<float>(sc);
  std::copy(image.begin(), image.end(), host);

  in.launch(*acc);  // 한 번만 업로드하면 이후에는 NPU 메모리에 상주합니다.

  std::vector<mobilint::NPUData> inputs = {in};
  std::vector<mobilint::NPUData> outputs = model->infer(inputs, sc);

  outputs[0].cpu();  // 결과를 호스트로 가져옵니다.
  const float* result = outputs[0].data<float>(sc);
  ```

  ```python
  # Python 예시
  npu_in = model.acquire_input_npu_data([224, 224, 3], idx=0, upload=False)
  npu_in[...] = image      # CPU에 있는 동안에는 numpy 뷰로 읽고 쓸 수 있습니다.
  npu_in.launch(acc)       # 한 번만 업로드하면 이후에는 NPU 메모리에 상주합니다.

  outputs = model.infer_npu_data([npu_in])
  print(outputs[0].dev_no, outputs[0].hardware_name)

  outputs[0].cpu()         # 결과를 호스트로 가져옵니다.
  result = outputs[0][...]
  ```

  한 번의 호출에 사용되는 모든 입력과 출력은 위치가 같아야 합니다. 즉 전부 호스트에 있거나 전부 NPU에 있어야 합니다. 모두 NPU에 있는 경우에는 재배치(reposition)와 호스트 복사가 전혀 발생하지 않습니다. 또한 NPU에 상주하는 텐서는 같은 가속기에서 동일한 형상·자료형을 기대하는 다른 모델에 그대로 전달할 수 있으므로, 연결된 모델들이 호스트를 거치지 않고 활성값을 주고받을 수 있습니다. Mixture-of-Experts 형태의 모델 구성이 바로 이 API가 목표로 하는 사용 방식입니다.

  `NPUData`는 일반적인 추론보다는 고급 사용을 위한 API이며, 단일 NPU 연산(CPU 오프로드 없음)이면서 재배치 가능한(MXQv7 이상) 모델에만 적용됩니다.

- **(베타) 하나의 MXQ 안에서 번들별로 다른 코어 모드 지원** — {doxylink}`setAutoCoreMode() <mobilint::ModelConfig::setAutoCoreMode()>`가 모델 전체에 대해 한 번이 아니라 번들마다 코어 모드를 판별합니다. 기준은 번들 단위입니다. 각 번들은 코어 모드를 정확히 하나만 지녀야 하며, 번들끼리는 서로 다른 코어 모드를 지녀도 됩니다. 이전에는 이런 MXQ에 `CoreMode::Auto`를 사용할 수 없었지만, 이제 하나의 모델로 실행됩니다. BatchLLM 최적화를 위해 개발된 기능이며, `ModelConfig` 기본 생성자가 이미 `CoreMode::Auto`를 사용하므로 별도의 코드 변경 없이 적용됩니다.

  ```cpp
  // C++ 예시
  mobilint::ModelConfig cfg;  // 기본값이 CoreMode::Auto입니다.
  cfg.setAutoCoreMode();
  auto model = mobilint::Model::create(MXQ_FILE_PATH, cfg, sc);
  ```

  ```python
  # Python 예시
  cfg = qbruntime.ModelConfig()
  cfg.set_auto_core_mode()
  model = qbruntime.Model(MXQ_FILE_PATH, cfg)
  ```

  반면 하나의 번들이 여러 코어 모드를 동시에 지니도록 컴파일된 경우(예: 컴파일러의 `scheme="all"`)에는 무엇을 선택할지 알 수 없어 `CoreMode::Auto`로 판별할 수 없습니다. 이때는 해당 번들을 알려주는 메시지와 함께 모델 생성이 실패하므로, 코어 모드를 직접 지정해야 합니다.

### 변경

- Windows 정적 라이브러리 배포판에서 발생하던 정적 초기화 순서 문제(SIOF)로 인한 비정상 종료를 해결했습니다.

### 삭제

- `ModelConfig::early_latencies`, `ModelConfig::finish_latencies` — 동작에 영향을 주지 않던 지원 중단 필드를 제거했습니다.

## v1.3.2

**출시일:** 2026년 7월 16일
**유형:** Patch

### 변경

- **v1.3.1 알려진 이슈 해결** — Windows에서 대형 모델 추론 시 발생하던 문제를 해결했습니다.

## v1.3.1

**출시일:** 2026년 7월 9일
**유형:** Minor

NPU 내부 16비트 정수 지원, SIMD 수준 선택, NPU 타임아웃 설정, RedHat 계열 OS용 DNF(RPM) 패키지 지원과 안정성 및 성능 개선이 포함되었습니다.

### 추가

- **16비트 정수형 지원** — NPU 내부 자료형으로 16비트 정수형을 지원합니다. 모델 입출력 자료형에는 영향이 없습니다.
- **RedHat 계열 OS용 DNF(RPM) 패키지** — RHEL, Rocky Linux(x86_64, aarch64)에서 모빌린트 DNF 저장소를 통해 `mobilint-qb-runtime`과 `mobilint-cli`를 설치할 수 있습니다. 설치 방법은 [런타임 라이브러리 설치](installing_runtime_library.md)를 참고하세요.
- **SIMD 수준 선택** — 스케일 및 전치 연산에서 AVX-512를 지원합니다. 기본적으로 시스템이 지원하는 가장 빠른 SIMD 수준을 자동으로 선택하며, `QBRUNTIME_SIMD_LEVEL` 환경 변수(`auto`, `avx512`, `avx2`, `sse2`)로 직접 지정할 수도 있습니다.
- **NPU 타임아웃 설정** — `QBRUNTIME_NPU_TIMEOUT_MS` 환경 변수로 qb Runtime이 NPU 응답을 기다리는 시간을 설정할 수 있습니다.

### 변경

- 가변 길이 입력을 사용하는 모델에서 `inferSpeedrun`을 실행할 때 더 이상 비정상 종료되지 않습니다.
- `inferAsync` API에서 발생하던 문제를 수정했습니다.
- `Model::releaseBuffer()`를 호출하지 않은 경우에도 `Model::dispose()`가 더 이상 3초 동안 대기하지 않습니다.
- Linux에서 추론 및 데이터 전송 성능을 개선했습니다.

### 알려진 문제

- **Windows에서 대형 모델 실행** — 7B LLM을 포함한 일부 대형 모델이 Windows에서 실행되지 않을 수 있습니다. 수정 작업이 진행 중이며 v1.3.2에 포함될 예정입니다.

## v1.2.0

**출시일:** 2026년 4월 2일
**유형:** Minor

Batch LLM 지원이 추가되었습니다.

### 추가

- **BatchParam** — Batch LLM 추론을 위한 새 구조체 {doxylink}`BatchParam <mobilint::BatchParam>`. 추론 시 각 배치에 필요한 정보를 담습니다:
    - `sequence_length` : 각 배치의 시퀀스 길이.
    - `cache_size` : 각 배치가 사용할 캐시 크기.
    - `cache_id` : 각 배치의 캐시 식별자. 동일한 컨텍스트의 모든 입력은 같은 캐시 ID를 사용해야 하며, 값은 모델이 지원하는 최대 배치 수 이내여야 합니다.

  Batch LLM을 사용하려면 여러 입력을 하나로 이어 붙인 뒤 — 형상이 `(1, seq_len, hidden_dim)`일 때 `seq_len` 차원 기준 — 각 입력에 대한 `BatchParam`을 전달합니다:

  ```python
  import qbruntime
  import numpy as np

  ## 모델이 지원하는 최대 배치 수를 확인합니다.
  print(model.get_cache_infos()[0].num_batches)

  ## 입력을 2번째 차원(axis=1)으로 이어 붙입니다.
  batch_input = np.concatenate([input0, input1], axis=1)

  ## qbruntime.BatchParam(sequence_length, cache_size, cache_id)
  batch_params = [
      qbruntime.BatchParam(10, 0, 0),
      qbruntime.BatchParam(80, 0, 1),
  ]
  res = model.infer([batch_input], params=batch_params)

  batch_params2 = [
      qbruntime.BatchParam(1, 10, 0),
      qbruntime.BatchParam(1, 80, 1),
  ]
  res = model.infer(res, params=batch_params2)
  ```

### 알려진 문제

- ARM(aarch64) 환경에서 LLM 모델 실행 시 "Bus Error"가 발생할 수 있습니다. v1.1.0부터 존재하는 문제이며, 드라이버 패치가 예정되어 있습니다.

## v1.1.0

**출시일:** 2026년 3월 23일
**유형:** Minor

자동 코어 모드 선택, 데이터 타입 조회 API, 성능 최적화가 포함되었습니다.

### 추가

- **`CoreMode::Auto`** — 런타임이 MXQ에서 사용 가능한 코어 모드를 자동으로 선택합니다. `ModelConfig`에 `CoreMode::Auto`를 설정하면(기본 생성자도 이미 Auto 사용) `Multi`, `Global4`, `Global8` 같은 비기본 모드를 수동으로 구성할 필요가 없습니다. {doxylink}`setAutoCoreMode() <mobilint::ModelConfig::setAutoCoreMode()>` 참고.
- `getModelInputDataType()` / `getModelOutputDataType()` — 런타임에 모델 입력/출력 데이터 타입을 조회합니다.
- `getAvailableDeviceNumbers()` — 사용 가능한 NPU 디바이스 번호 목록을 가져옵니다.

```{note}
`scheme="all"`처럼 여러 코어 모드를 생성하는 플래그로 컴파일된 MXQ는 기존과 같이 코어 모드를 수동으로 선택해야 합니다.
```

### 변경

- REGULUS에도 v1.0.0에서 도입된 동적 할당 방식이 적용되어 일관된 사용 패턴을 제공합니다.
- Windows에서 NPU 디바이스로의 데이터 전송 성능을 개선했습니다.
- 내부 타입 변환을 최적화했습니다.
- GCC 9 미만에서 `std::filesystem`으로 인한 컴파일 오류를 수정했습니다.
- 특정 모델에서 간헐적으로 발생하던 데드락을 수정했습니다.
- **[Breaking]** 지원되는 REGULUS 드라이버 리비전이 REV0에서 REV1로 변경됩니다.

### 알려진 문제

- ARM(aarch64) 환경에서 LLM 모델 실행 시 "Bus Error"가 발생할 수 있습니다. 드라이버 패치가 예정되어 있습니다.

```{seealso}
전체 변경 이력은 [Changelog](CHANGELOG.md) 페이지를 참고하세요.
```

## v1.0.0

**출시일:** 2026년 1월 31일
**유형:** Major

확장성, 일관성, 그리고 향후 확장을 위한 구조 개편에 중점을 둔 메이저 릴리즈입니다. 업그레이드하려면 [마이그레이션 가이드](migration_guide.md)를 따라주세요.

### 추가

- **uint8 추론** — uint8 양자화 모델을 qb Compiler로 컴파일하고 qb Runtime으로 실행할 수 있습니다. uint8 입력을 사용하는 모델의 전처리 시 CPU 부하를 줄여줍니다.
- **액티베이션 슬롯** — `setActivationSlots(int num)`(C++)와 `set_activation_slots(num)`(Python)으로 NPU 추론과 데이터 전송 간 파이프라이닝을 조정합니다. 슬롯이 많을수록 NPU 메모리 사용량은 늘지만 멀티스레드 환경의 처리량이 향상됩니다.

```{note}
캐시를 사용하는 모델(예: LLM)에서는 현재 액티베이션 슬롯 수가 1로 제한됩니다.
```

### 변경

- **[Highlight]** 모델 수 제한 제거 — 최신 qb Compiler(MXQv7)로 컴파일된 모델은 컴파일 시 지정한 코어 모드와 무관하게, 가용 DRAM 범위 내에서 동시에 로드·실행됩니다. 다중 모델 서비스, 서로 다른 코어 모드 혼합 실행, LLM 같은 대형 모델에 도움이 되며 코드 변경이 필요 없습니다.
- **[Breaking]** SDK qb 명칭 통일 — 런타임 라이브러리 `maccel` → **qb Runtime**, 컴파일러 `qubee` → **qb Compiler**. 패키지·헤더·모듈 이름도 이에 맞게 변경되었습니다.

### 삭제

- 레거시 패키지(`mobilint-npu-runtime`, `aries-driver`)는 더 이상 유지보수되지 않습니다. [마이그레이션 가이드](migration_guide.md)를 참고하세요.
