콘텐츠로 이동

RBLN PyTorch API 및 지원 연산

이 페이지는 RBLN PyTorch의 레퍼런스 문서입니다. rbln 백엔드의 디바이스 모듈로 등록되는 torch.rbln과 RBLN NPU에서 실행하는 PyTorch 연산자를 정리합니다. 대부분의 PyTorch 코드는 RBLN 전용 함수를 호출할 필요가 없습니다. torch.rbln API는 디바이스 선택, 동기화, 스트림, 메모리, 진단에 사용하며 대응 API가 있는 경우 torch.cuda와 같은 방식으로 사용합니다.

torch.rbln 모듈

import torch를 실행하면 torch.rbln이 자동으로 등록됩니다. 다음 표는 모든 공개 심볼을 그룹별로 나누고 대응하는 torch.cuda API가 있으면 함께 표시합니다. 각 표 뒤에는 소스 docstring에서 생성한 상세 시그니처가 이어집니다.

디바이스 관리

API torch.cuda 대응 API 요약
torch.rbln.is_available() is_available RBLN을 가속기로 사용할 수 있는지 반환합니다. 예외를 발생시키지 않으며 런타임이 없거나 디바이스가 보이지 않거나 RBLN_* 디바이스 설정이 잘못되면 False를 반환합니다.
torch.rbln.device_count() device_count 논리 RBLN 디바이스 수입니다. 예외를 발생시키지 않으며 앞과 같은 경우 0을 반환합니다. 설정이 잘못되면 경고를 표시합니다.
torch.rbln.physical_device_count() — RSD 그룹 설정과 관계없이 프로세스에 보이는 물리 NPU 수입니다. 디바이스를 점유하거나 매핑을 확정하지 않습니다.
torch.rbln.current_device() current_device 현재 선택한 논리 디바이스의 인덱스입니다.
torch.rbln.set_device(device) set_device 현재 디바이스를 선택합니다. 관리 상태만 변경하며 NPU를 점유하지 않습니다. torch.rbln.device 컨텍스트 관리자를 권장합니다.
torch.rbln.device(device) device 선택한 디바이스를 변경하고 종료 시 이전 디바이스로 복원하는 컨텍스트 관리자입니다.
torch.rbln.device_of(obj) device_of 주어진 텐서의 디바이스를 선택하는 컨텍스트 관리자입니다.
torch.rbln.synchronize(device=None) synchronize 디바이스에서 대기 중인 비동기 전송이 끝난 뒤 해당 디바이스의 모든 스트림이 완료될 때까지 기다립니다.
torch.rbln.is_initialized() is_initialized 디바이스를 선택했거나 디바이스가 없으면 True를 반환합니다.
torch.rbln.is_dummy_device() — NPU가 아닌 호스트 기반 더미 디바이스에서 실행 중이면 True를 반환합니다.
torch.rbln.device_summary() — 논리 디바이스와 물리 NPU의 매핑 표, 사용하지 않는 NPU가 있으면 경고를 출력합니다.
torch.rbln.get_device_properties(device=None) get_device_properties 논리 디바이스에 속한 NPU의 속성입니다. name, total_memory(논리 디바이스에 속한 NPU의 메모리 합계), npu_count, NPU별 num_chiplet과 memory_per_chiplet을 표시합니다. 메모리를 할당하거나 디바이스를 점유하지 않습니다. 더미 디바이스에서는 예외가 발생합니다.
torch.rbln.get_device_name(device=None) get_device_name 논리 디바이스에 속한 NPU의 이름입니다. 예: "RBLN-CA25".
torch.rbln.get_amp_supported_dtype() get_amp_supported_dtype RBLN에서 자동 혼합 정밀도를 지원하는 dtype입니다. 이번 릴리스에는 autocast dtype이 등록되지 않아 빈 목록을 반환합니다.

Rebellions Scalable Design(RSD)으로 여러 ATOM™ NPU를 하나의 rbln:N으로 묶으면 논리 디바이스와 물리 NPU가 달라집니다. Rebel100™ 카드는 칩렛 네 개로 구성된 고정 RSD-4 그룹이며 항상 1:1로 매핑됩니다. device_count()는 논리 디바이스 수를, physical_device_count()는 보이는 물리 NPU 수를 반환합니다. 그룹 설정에 사용하는 RBLN_DEVICE_MAP과 RBLN_NPUS_PER_DEVICE는 환경 변수에서 설명합니다. 같은 이유로 get_device_properties()의 total_memory는 논리 디바이스에 속한 NPU의 메모리를 합산하고 memory_per_chiplet은 칩렛별 값을 표시합니다. 메모리 사용량이 가장 큰 칩렛에서 메모리가 부족해지므로 메모리 풀 크기는 memory_per_chiplet을 기준으로 결정해야 합니다.

device(device)

Context-manager that changes the selected device.

Parameters:

Name Type Description Default
device torch.device, int, str, or None

device index to select. It is a no-op if this argument is a negative integer or None.

required
Example
with torch.rbln.device(0):
    x = torch.randn(2, 2, device="rbln:0")

device_of(obj)

Context-manager that changes the current device to that of given object.

You can use both tensors and storages as arguments. If a given object is not allocated on an RBLN device, this is a no-op.

Parameters:

Name Type Description Default
obj Tensor or Storage

object allocated on the selected device.

required
Example
1
2
3
4
tensor = torch.tensor([2, 64], device="rbln:1")
with torch.rbln.device_of(tensor):
    # operations here will use the same device as tensor (rbln:1)
    new_tensor = torch.zeros(3, device="rbln")

is_available()

Check if any RBLN devices are available.

Returns:

Name Type Description
bool bool

True if at least one RBLN device is available, False otherwise.

device_count()

Get the number of available RBLN devices.

Returns:

Name Type Description
int int

The number of available RBLN devices.

physical_device_count()

Get the number of physical RBLN devices in the system.

This function returns the actual number of physical devices, regardless of whether logical device aggregation is enabled.

Returns:

Name Type Description
int int

The number of physical RBLN devices.

current_device()

Get the index of the currently selected RBLN device.

Returns:

Name Type Description
int int

The index of the currently selected RBLN device.

set_device(device)

Set the current device.

Parameters:

Name Type Description Default
device device or int or str

selected device.

required

synchronize(device=None)

Wait for all work on the given RBLN device: its pending asynchronous transfers, then every stream on it (torch.cuda.synchronize parity).

If no device is specified, the current device is used.

Parameters:

Name Type Description Default
device device or int or str

The device to synchronize. Defaults to the current device.

None
Example
cpu_tensor = rbln_tensor.to("cpu", non_blocking=True)
torch.rbln.synchronize()  # wait for the transfer to complete

is_initialized()

True once set_device() has run, or when there are no devices at all.

The no-device case is deliberate: it makes torch.distributed's init_device_mesh skip its get_rank() % device_count() auto-select, which would otherwise fail on a host with no NPU.

Note: this calls device_count(), which plans the RBLN device mapping from the current RBLN_* environment. It does not claim an NPU or freeze the mapping; both happen on first device use, so a launcher may still assign RBLN_DEVICES afterwards.

is_dummy_device()

Whether the process runs on a host-backed dummy device rather than an NPU.

is_available() is True on a dummy device too, so use this to tell a dummy device apart from real NPU availability.

Returns:

Name Type Description
bool bool

True on a dummy device, False otherwise.

device_summary()

Print a summary of the RBLN device topology showing the mapping between logical devices and physical NPU IDs.

The table shows:

  • Logical device indices (rbln:0, rbln:1, ...)
  • Physical NPU IDs mapped to each logical device
  • Status of each device (Active, Active (Aggregated), or Unused)
  • A warning about unused physical devices, if any

The device mapping is determined by the following environment variables (in order of priority):

  1. RBLN_DEVICE_MAP: explicit groups, for example "[0,1],[2,3,4,5]"
  2. RBLN_NPUS_PER_DEVICE: uniform groups of the given size, for example "2"
Example
1
2
3
import torch

torch.rbln.device_summary()
1
2
3
4
5
6
7
[RBLN] Device Topology Initialized:
+----------------+------------------+---------------------+
| Logical Device | Physical NPU IDs | Status              |
+----------------+------------------+---------------------+
| rbln:0         | [ 0, 1 ]         | Active (Aggregated) |
| rbln:1         | [ 2, 3 ]         | Active (Aggregated) |
+----------------+------------------+---------------------+

get_device_properties(device=None)

Describe the NPUs behind an RBLN logical device (torch.cuda parity).

A logical device may span several physical NPUs (RBLN_DEVICE_MAP / RBLN_NPUS_PER_DEVICE), so total_memory sums them and npu_count says how many. num_chiplet and memory_per_chiplet stay per NPU: a device runs out on its heaviest chiplet, which total_memory hides, so size a pool by memory_per_chiplet.

The query does not allocate memory or claim the device, so it is safe to call before the runtime initializes. Properties are not cached: each call queries every NPU behind the logical device.

Parameters:

Name Type Description Default
device device or int or str

The device to query. Defaults to the current device.

None

Returns:

Name Type Description
DeviceProperties DeviceProperties

An object with the read-only attributes name (the NPU name, for example "RBLN-CA25"), total_memory (bytes, summed over the NPUs of the logical device), npu_count, num_chiplet (per NPU), and memory_per_chiplet (bytes, per chiplet).

Raises:

Type Description
RuntimeError

on a dummy device (host-backed, no NPU to report on), when no NPU is mapped to the index, when the runtime cannot answer for one of them, or when the NPUs of the logical device differ in name or chiplet count.

Example
props = torch.rbln.get_device_properties(0)
props.total_memory  # 150323855360

get_device_name(device=None)

Return the NPU name behind an RBLN logical device, for example "RBLN-CA25" (torch.cuda parity).

Same as get_device_properties(device).name.

Parameters:

Name Type Description Default
device device or int or str

The device to query. Defaults to the current device.

None

Returns:

Name Type Description
str str

The NPU name.

get_amp_supported_dtype()

Get a list of data types supported by automatic mixed precision (AMP) on RBLN devices.

Returns:

Type Description
List[dtype]

List[torch.dtype]: A list of data types supported by AMP.

Note

Automatic mixed precision is not implemented for RBLN devices yet, so this currently returns an empty list. As a result, entering torch.autocast("rbln") emits a warning and leaves autocast disabled instead of raising an error.

난수 생성

이 함수들은 가속기의 RNG 상태를 저장하고 복원하는 torch.random.fork_rng 같은 PyTorch 유틸리티가 rbln에서 동작하도록 합니다. 각 rbln 디바이스에는 고유한 상태를 가진 기본 generator가 있습니다. 이번 릴리스에서 rbln의 난수 생성 연산자는 여전히 CPU에 고정되어 있습니다. generator 인자 없이 호출하면 PyTorch의 기본 CPU generator가 아니라 대상 rbln 디바이스의 기본 generator를 사용합니다. 이 함수들이 저장하고 복원하는 상태는 CPU에 고정된 난수 연산자에만 영향을 줍니다. 아직 디바이스 커널 내부의 난수 상태에는 영향을 주지 않으므로 이 상태를 설정해도 vLLM의 무작위 샘플링처럼 디바이스에서 생성한 결과의 재현성을 보장하지 않습니다.

API torch.cuda 대응 API 요약
torch.rbln.get_rng_state(device="rbln") get_rng_state 디바이스의 RNG 상태를 ByteTensor로 반환합니다. 인덱스 없는 "rbln"은 현재 디바이스를 뜻합니다.
torch.rbln.get_rng_state_all() get_rng_state_all 모든 논리 디바이스의 RNG 상태를 디바이스 인덱스 순서로 반환합니다.
torch.rbln.set_rng_state(new_state, device="rbln") set_rng_state get_rng_state()에서 받은 상태로 해당 디바이스의 RNG 상태를 복원합니다.
torch.rbln.set_rng_state_all(new_states) set_rng_state_all get_rng_state_all()에서 받은 순서에 따라 모든 디바이스의 RNG 상태를 복원합니다.

get_rng_state(device='rbln')

Return the random number generator state of device as a ByteTensor (torch.cuda.get_rng_state parity).

Parameters:

Name Type Description Default
device device or int or str

The device to query. Defaults to "rbln", the current device.

'rbln'

Returns:

Type Description
Tensor

torch.Tensor: The generator state.

get_rng_state_all()

Return the random number generator state of every device, in device-index order.

Returns:

Type Description
List[Tensor]

List[torch.Tensor]: One state per logical device.

set_rng_state(new_state, device='rbln')

Set the random number generator state of device.

Parameters:

Name Type Description Default
new_state Tensor

A state produced by get_rng_state().

required
device device or int or str

The device to set. Defaults to "rbln", the current device.

'rbln'

set_rng_state_all(new_states)

Set the random number generator state of every device.

Parameters:

Name Type Description Default
new_states Iterable[Tensor]

States ordered like the result of get_rng_state_all().

required

스트림과 이벤트

스트림과 이벤트는 torch.cuda.Stream, torch.cuda.Event와 같은 방식으로 사용합니다. 범용 클래스인 torch.Stream, torch.Event에서도 device="rbln"로 접근할 수 있습니다.

API torch.cuda 대응 API 요약
torch.rbln.Stream(device=None, priority=0) Stream 디바이스 작업을 순서대로 실행하는 스트림입니다. 스트림 간 순서는 이벤트로 제어합니다. 이번 릴리스에서는 스트림을 나누어도 디바이스 측 병렬성이 추가되지 않습니다(실행 방식 › 스트림 참고). priority는 API 정합성을 위해 받지만 무시합니다. 스트림은 디바이스별 고정 풀에서 가져오며 풀 크기를 초과하면 이전 스트림을 재사용합니다.
torch.rbln.Event(enable_timing=False, blocking=False, interprocess=False) Event 스트림에 기록하여 스트림 간 순서를 제어하고 완료 여부를 조회하는 마커입니다. 세 플래그는 받지만 무시하며 elapsed_time()은 지원하지 않습니다. 프로세스 간 공유도 지원하지 않습니다. ipc_handle()과 from_ipc_handle()은 NotImplementedError를 발생시킵니다.
torch.rbln.current_stream(device=None) current_stream 디바이스에서 현재 선택한 스트림입니다.
torch.rbln.default_stream(device=None) default_stream 디바이스의 기본 스트림입니다.
torch.rbln.stream(stream) stream stream을 현재 스트림으로 선택하고 종료 시 이전 스트림으로 복원하는 컨텍스트 관리자입니다. None이면 아무 작업도 하지 않습니다.
torch.rbln.set_stream(stream) set_stream 현재 스트림을 설정합니다. stream 컨텍스트 관리자를 권장합니다.
torch.rbln.StreamContext StreamContext stream()에서 사용하는 컨텍스트 관리자 클래스입니다.

Stream(device=None, priority=0)

An in-order sequence of device work on an RBLN NPU.

Work submitted to the same stream runs in order, while work on different streams may run concurrently. Use a stream to overlap a copy with compute, and an Event to order work between two streams.

Streams come from a fixed per-device pool. Once the pool is exhausted, new instances reuse earlier streams.

Parameters:

Name Type Description Default
device torch.device, int, str, or None

The device the stream belongs to. If None, uses the current device. Defaults to None.

None
priority int

Accepted for API parity and ignored, because RBLN NPUs have no stream priorities. Defaults to 0.

0
Example
1
2
3
4
s = torch.rbln.Stream()
with torch.rbln.stream(s):
    y = x * 2
s.synchronize()
query()

Check whether all work submitted to this stream has completed.

Returns:

Name Type Description
bool bool

True if the stream has no pending work.

synchronize()

Block the calling host thread until all work submitted to this stream completes.

Waits on this stream only. A pending asynchronous transfer is tracked per device, not per stream, so use torch.rbln.synchronize() to wait for those.

wait_event(event)

Make all future work submitted to this stream wait for event.

A device-side fence when event was recorded on this stream's device: the call returns without blocking the host. RBLN has no cross-device fence, so an event recorded on another device is waited on the host instead. Ordering holds either way; what changes is that the caller is serialized.

Parameters:

Name Type Description Default
event Event

The event to wait for.

required
wait_stream(stream)

Make all future work submitted to this stream wait for the work already submitted to stream.

Records an event on stream and waits for it, so the cross-device rule in wait_event() applies here too.

Parameters:

Name Type Description Default
stream Stream

The stream to synchronize with.

required
record_event(event=None)

Record an event in this stream.

Parameters:

Name Type Description Default
event Event

The event to record. A new event is created if None. Defaults to None.

None

Returns:

Name Type Description
Event Event

The recorded event.

Event(enable_timing=False, blocking=False, interprocess=False)

A marker recorded in a stream, used to order work across streams and to query completion.

RBLN NPUs do not support event timing: elapsed_time() raises a RuntimeError, and the constructor flags are accepted for API parity but ignored. Waiting on an event recorded on another device falls back to a host-side synchronize.

Cross-process event sharing is not supported: ipc_handle() and from_ipc_handle() are inherited from torch.Event and raise NotImplementedError: torch.Event ipc is not supported yet, so interprocess=True grants no capability. Both attributes are present, so a capability probe that only looks them up succeeds and the failure surfaces at the call.

Parameters:

Name Type Description Default
enable_timing bool

Accepted for API parity and ignored. Defaults to False.

False
blocking bool

Accepted for API parity and ignored. Defaults to False.

False
interprocess bool

Accepted for API parity and ignored; RBLN events cannot be shared across processes. Defaults to False.

False
Example
producer = torch.rbln.Stream()
consumer = torch.rbln.Stream()
# An asynchronous upload needs a pinned source and a destination with device memory.
host_weights = torch.randn(1024, 1024, dtype=torch.float16).pin_memory()
w = torch.empty_like(host_weights, device="rbln")
torch.rbln.bind_device_memory(w)

copy_done = torch.rbln.Event()
with torch.rbln.stream(producer):
    w.copy_(host_weights, non_blocking=True)
    copy_done.record()

consumer.wait_event(copy_done)  # work on consumer waits for the copy; the host does not block
with torch.rbln.stream(consumer):
    y = w * 2
record(stream=None)

Record the event in a stream.

Parameters:

Name Type Description Default
stream Stream

The stream to record in. If None, uses the current stream. Defaults to None.

None
wait(stream=None)

Make all future work submitted to a stream wait for this event.

Parameters:

Name Type Description Default
stream Stream

The stream that waits. If None, uses the current stream. Defaults to None.

None
query()

Check whether the work captured by this event has completed.

Returns:

Name Type Description
bool bool

True if every work item recorded before the event has completed.

synchronize()

Block the calling host thread until the work captured by this event completes.

StreamContext(stream)

Context-manager that selects a given stream, restoring the previously selected one on exit.

The stream's device is selected for the duration. Create one with stream().

Parameters:

Name Type Description Default
stream Stream or None

The stream to select. It is a no-op if None.

required

current_stream(device=None)

Return the currently selected stream for a given device.

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Name Type Description
Stream Stream

The currently selected stream.

default_stream(device=None)

Return the default stream for a given device.

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Name Type Description
Stream Stream

The default stream.

stream(stream)

Return a context manager that selects the given stream.

Parameters:

Name Type Description Default
stream Stream or None

The stream to select. It is a no-op if None.

required

Returns:

Name Type Description
StreamContext StreamContext

A context manager that restores the previously selected stream on exit.

Example
1
2
3
s = torch.rbln.Stream()
with torch.rbln.stream(s):
    y = x * 2

set_stream(stream)

Select a stream for all subsequent work, and select its device as well.

This sets the stream for the remainder of the calling thread. Prefer the stream context manager, which restores the previous stream on exit.

Parameters:

Name Type Description Default
stream Stream or None

The stream to select. It is a no-op if None.

required

메모리

통계 API는 캐싱 할당기가 관리하는 디바이스 메모리를 표시합니다. 디바이스 메모리는 지연 할당하므로 rbln에 생성한 텐서는 디바이스 연산이 메모리를 실제 할당하기 전까지 통계에 포함되지 않습니다. 자세한 내용은 실행 방식에서 확인할 수 있습니다. Rebel100™ 카드 하나에는 칩렛 네 개로 구성된 칩 하나가 있으며 할당기는 칩렛별로 메모리를 추적합니다. memory_summary()와 memory_stats_per_chiplet()은 칩렛별 내역을 표시하고 나머지 통계는 칩렛 전체를 합산합니다(실행 방식 › Rebel100™과 ATOM™ 참고). mem_get_info()와 mem_get_info_per_chiplet()은 예외입니다. 현재 프로세스의 할당기가 확보한 메모리가 아니라 모든 프로세스에 걸쳐 커널 드라이버가 보는 디바이스 메모리를 표시합니다.

API torch.cuda 대응 API 요약
torch.rbln.memory_allocated(device=None) memory_allocated 디바이스에서 텐서가 현재 사용하는 바이트 수입니다.
torch.rbln.max_memory_allocated(device=None) max_memory_allocated 마지막 최댓값 초기화 이후 텐서가 사용한 바이트 수의 최댓값입니다.
torch.rbln.memory_reserved(device=None) memory_reserved 캐시에 보관한 빈 블록을 포함하여 캐싱 할당기가 현재 관리하는 바이트 수입니다.
torch.rbln.max_memory_reserved(device=None) max_memory_reserved 캐싱 할당기가 관리한 바이트 수의 최댓값입니다.
torch.rbln.memory_stats(device=None) memory_stats allocated.current, allocated.peak, reserved.current, active.peak 같은 점으로 구분한 키를 사용하는 할당기 통계 사전입니다.
torch.rbln.memory_stats_per_chiplet(device=None) — 같은 통계를 칩렛별로 나누며 각 키에는 npu.<n>.chiplet.<c>. 접두사가 붙습니다. 합산 통계에는 드러나지 않더라도 메모리 사용량이 가장 큰 칩렛에서 메모리가 부족해질 수 있습니다.
torch.rbln.memory_summary(device=None) memory_summary 논리 디바이스의 NPU와 칩렛마다 한 행씩 표시하는, 텍스트 형식의 할당기 통계 표입니다.
torch.rbln.mem_get_info(device=None) mem_get_info 드라이버가 모든 프로세스에 걸쳐 보고하는 디바이스 메모리 (free, total) 바이트 값입니다. rbln의 torch.accelerator.get_memory_info와 같은 값이며 total은 카드의 명목 메모리보다 작습니다. RBLN 디바이스가 없거나 더미 디바이스이거나 설치된 드라이버가 조회를 지원하지 않으면 예외가 발생합니다.
torch.rbln.mem_get_info_per_chiplet(device=None) — 드라이버가 보고하는 칩렛별 값(npu.<n>.chiplet.<c>.{total,used,free,largest_free,largest_free_huge})과 NPU별 값(npu.<n>.{total,used,free,granularity,huge_granularity})입니다. npu.<n>은 물리 NPU ID가 아니라 논리 디바이스 안의 NPU 위치입니다. 연속 버퍼 크기는 한 칩렛의 largest_free로 제한되며 디바이스 전체의 free만으로는 이 제한을 알 수 없습니다.
torch.rbln.reset_peak_memory_stats(device=None) reset_peak_memory_stats 최댓값 카운터를 초기화합니다.
torch.rbln.reset_accumulated_memory_stats(device=None) reset_accumulated_memory_stats 누적 카운터를 초기화합니다.
torch.rbln.empty_cache(device=None) empty_cache 사용하지 않는 캐시 디바이스 메모리를 반환합니다. 컴파일 프로그램의 웜 캐시와 뷰 레시피 캐시도 비우므로 호출자가 더 이상 보유하지 않는 메모리를 모두 반환합니다.
torch.rbln.bind_device_memory(tensor) — 첫 사용을 기다리지 않고 텐서의 디바이스 메모리를 즉시 할당합니다. 집합 통신 라이브러리나 직접 스토리지 DMA처럼 PyTorch 연산자를 거치지 않고 디바이스 메모리를 읽는 소비자에게 버퍼를 전달하기 전에 필요합니다. 텐서는 스토리지 전체를 포함해야 합니다.
torch.rbln.set_device_layout_like(target, ref) — 복사 없이 target의 디바이스 할당 레이아웃을 디바이스에 상주하는 텐서 ref와 맞춰 이후 두 텐서 간 디바이스 복사가 빠른 경로를 사용하도록 합니다. 두 텐서는 같은 디바이스와 dtype의 RBLN 텐서여야 합니다.
torch.rbln.huge_host_empty(nbytes) — 디바이스가 스테이징 복사 없이 DMA할 수 있는 2 MiB 정렬 호스트 버퍼를 할당하며 페이지도 미리 확보합니다. 0으로 채운 1차원 uint8 CPU 텐서를 반환합니다. Transparent huge page는 가능한 범위에서 요청합니다.
torch.rbln.offload() — 블록 안에서 할당한 RBLN 텐서의 호스트 영역에 파일 오프로딩을 활성화하는 컨텍스트 관리자입니다. 중첩 블록은 참조 횟수로 관리합니다. 파일은 RBLN_OFFLOAD_DIR에 저장합니다(기본값 $HOME/.cache/rbln_cache/offload).
torch.rbln.release_offload_temp_storage() — 현재 프로세스의 임시 오프로딩 파일을 제거합니다. 런타임 자체 정리 전에 종료될 수 있는 종료 경로에서 호출합니다. 이후 오프로딩한 텐서를 사용하면 안 됩니다. 제거한 파일 수를 반환합니다.

memory_allocated(device=None)

Return the current device memory occupied by tensors in bytes for a given device.

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Name Type Description
int int

The current memory occupied by tensors in bytes.

Note

This function reflects device memory only. For information about lazy memory allocation, see memory_stats().

max_memory_allocated(device=None)

Return the maximum device memory occupied by tensors in bytes for a given device.

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Name Type Description
int int

The maximum memory occupied by tensors in bytes.

Note

This function reflects device memory only. For information about lazy memory allocation, see memory_stats().

memory_reserved(device=None)

Return the current device memory managed by the caching allocator in bytes for a given device.

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Name Type Description
int int

The current memory managed by the caching allocator in bytes.

Note

This function reflects device memory only. For information about lazy memory allocation, see memory_stats().

max_memory_reserved(device=None)

Return the maximum device memory managed by the caching allocator in bytes for a given device.

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Name Type Description
int int

The maximum memory managed by the caching allocator in bytes.

Note

This function reflects device memory only. For information about lazy memory allocation, see memory_stats().

memory_stats(device=None)

Return a dictionary of device memory allocator statistics for a given device.

The returned dictionary contains various memory statistics including:

  • allocated.current: Current memory occupied by tensors
  • allocated.peak: Peak memory occupied by tensors
  • allocated.total_allocated: Total memory allocated to tensors (cumulative)
  • allocated.total_freed: Total memory freed from tensors (cumulative)
  • reserved.current: Current memory managed by the caching allocator
  • reserved.peak: Peak memory managed by the caching allocator
  • reserved.total_allocated: Total memory allocated by the caching allocator (cumulative)
  • reserved.total_freed: Total memory freed by the caching allocator (cumulative)
  • active.current: Current size of blocks in use (may differ from allocated due to block granularity)
  • active.peak: Peak size of blocks in use
  • cached.current: Current size of cached blocks available for reuse
  • cached.peak: Peak size of cached blocks
  • num_alloc_retries: Number of allocation retries after cache flush
  • num_ooms: Number of out-of-memory errors
  • num_device_alloc: Number of device memory acquisitions
  • num_device_free: Number of device memory releases

Lazy Tensor Memory Allocation: All memory-related functions in this module (including memory_allocated(), memory_reserved(), max_memory_allocated(), max_memory_reserved(), and this function) reflect device memory only, not CPU memory.

RBLN tensors use lazy memory allocation for device memory. When you create a tensor on an RBLN device:

  • The tensor is initially allocated in CPU memory immediately upon creation
  • Device memory allocation is deferred until the tensor is actually needed for device operations
  • When a device operation is required, the tensor data is lazily transferred from CPU to device memory

This lazy allocation strategy means that memory statistics may be lower than expected immediately after tensor creation until the tensors are used in device computations. Device memory statistics will increase when tensors are materialized on the device during actual computation.

The statistics also include lazy tensor related metrics, which provide insights into the memory management for tensors that have not yet been materialized on the device. The specific lazy tensor statistics fields may vary depending on the implementation version.

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Type Description
Dict[str, int]

Dict[str, int]: A dictionary containing device memory statistics. Note that these statistics reflect device memory only (not CPU memory) and may not include memory for tensors that have not yet been transferred to the device.

Note

To see accurate device memory usage, check statistics after performing operations that require the tensors to be materialized on the device, as device memory is allocated lazily when needed. This applies to all memory-related functions in this module.

memory_stats_per_chiplet(device=None)

Return memory allocator statistics broken down per chiplet.

Same keys as memory_stats(), each prefixed with npu.<n>.chiplet.<c>. -- e.g. npu.0.chiplet.0.allocated.current. A device runs out on its heaviest chiplet, which the aggregate memory_stats() hides.

npu.<n> is the n-th physical NPU of this logical device (RBLN_NPUS_PER_DEVICE / RBLN_DEVICE_MAP), not a physical NPU id; a 1:1 mapping yields npu.0 only. Same scope as memory_stats().

Parameters:

Name Type Description Default
device Optional[Union[int, str, device]]

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Type Description
Dict[str, int]

Dict[str, int]: A dictionary containing per-chiplet memory statistics.

memory_summary(device=None)

Return a human-readable printout of the current memory allocator statistics.

Rows are per (NPU, chiplet), so an imbalance is visible at a glance. The scope line under the title names what the numbers cover: they are this process's allocator, not the NPU's occupancy (see memory_stats()). The npu column is the physical NPU id as torch.rbln.device_summary() prints it: relative to RBLN_VISIBLE_DEVICES, so it differs from rbln-smi when that variable is set. A logical device grouping several NPUs (RBLN_NPUS_PER_DEVICE / RBLN_DEVICE_MAP) gets one row per NPU.

Peaks are tracked per chiplet, so the peak columns of the total row bound the joint peak from above rather than reporting it. memory_stats() carries the exact joint peak.

Parameters:

Name Type Description Default
device Optional[Union[int, str, device]]

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Name Type Description
str str

The formatted table, or a short notice when no stats are available.

mem_get_info(device=None)

Return the free and total device DRAM of device in bytes, as (free, total).

Same contract as torch.cuda.mem_get_info, and what torch.accelerator.get_memory_info reports for rbln: the NPU's figures as the kernel driver sees them, across every process, not this process's caching allocator, which memory_stats() covers. total is the pool the driver can hand out, so it sits below the part's nominal DRAM. A logical device spanning several physical NPUs (RBLN_NPUS_PER_DEVICE / RBLN_DEVICE_MAP) reports their sum; one tensor still lives on one NPU. The result is a reading, not a reservation: another process may allocate right after.

Parameters:

Name Type Description Default
device Optional[Union[int, str, device]]

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Type Description
Tuple[int, int]

Tuple[int, int]: (free, total) in bytes.

Raises:

Type Description
RuntimeError

if there is no RBLN device, the device is a dummy device, or the installed driver does not provide the device memory query.

mem_get_info_per_chiplet(device=None)

Return the driver's device DRAM usage of device broken down per chiplet, in bytes.

Same figures as mem_get_info() before summation, keyed like memory_stats_per_chiplet(): npu.<n>.chiplet.<c>.{total,used,free,largest_free, largest_free_huge} for each chiplet, and npu.<n>.{total,used,free,granularity, huge_granularity} for each physical NPU of the logical device. npu.<n> is the NPU's position within the logical device, not a physical NPU id.

Each chiplet allocates from its own pool, so a physically contiguous buffer is bounded by one chiplet's largest_free (largest_free_huge for the huge granule; 0 where the part has none), which the device-wide free hides. largest_free may exceed free in the same reply: both are estimates from a lock-free walk.

Parameters:

Name Type Description Default
device Optional[Union[int, str, device]]

The device to query. If None, uses the current device. Defaults to None.

None

Returns:

Type Description
Dict[str, int]

Dict[str, int]: A map from key to bytes.

Raises:

Type Description
RuntimeError

under the same conditions as mem_get_info().

reset_peak_memory_stats(device=None)

Reset the "peak" stats tracked by the caching allocator for a given device.

This function resets the peak values to their current values for the following stats:

  • allocated.peak: Reset to allocated.current
  • reserved.peak: Reset to reserved.current
  • active.peak: Reset to active.current
  • cached.peak: Reset to cached.current

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to reset stats for. If None, uses the current device. Defaults to None.

None

reset_accumulated_memory_stats(device=None)

Reset the "accumulated" (historical) stats tracked by the caching allocator for a given device.

This function resets the following accumulated stats to zero:

  • allocated.total_allocated
  • allocated.total_freed
  • reserved.total_allocated
  • reserved.total_freed
  • num_alloc_retries
  • num_ooms
  • num_device_alloc
  • num_device_free

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to reset stats for. If None, uses the current device. Defaults to None.

None

empty_cache(device=None)

Release all unoccupied cached memory currently held by the caching allocator so that those can be used in other application.

Note that only unfragmented (non-split) blocks can be released; fragmented blocks that have been split will remain in the cache until they can be coalesced.

Parameters:

Name Type Description Default
device int, str, or torch.device

The device to empty cache for. If None, uses the current device. Defaults to None.

None

bind_device_memory(tensor)

Materialize tensor's device allocation instead of leaving it lazy.

A device allocation reserves a virtual address and materializes the physical memory behind it on first use through a torch op. A consumer that reads those physical buffers out of band, such as a collective library or direct storage (NVMe) DMA, never runs such an op, so it would find nothing there. Call this after allocating a buffer you are handing to one.

The region is laid out flat and 1:1 with no dtype transform, on the device's main node, which is what a consumer treating it as bytes expects. Use set_device_layout_like() instead when the layout has to match another tensor's. Binding an already-bound region is allowed.

Parameters:

Name Type Description Default
tensor Tensor

An RBLN tensor covering its whole storage: contiguous, with zero storage offset. A view that still spans the whole storage is fine; a slice or an interior view is not, since its address is not the allocation's.

required

Raises:

Type Description
RuntimeError

if tensor is not an RBLN tensor, does not cover its whole storage, or the runtime rejects the allocation.

Example
staging = torch.empty(nbytes, dtype=torch.uint8, device="rbln:0")
torch.rbln.bind_device_memory(staging)

set_device_layout_like(target, ref)

Configure target's device-allocation layout to match ref (no copy).

Both must be RBLN tensors with the same dtype, on the same device, and each covering its whole storage. ref must be device-resident. target adopts ref's layout and dtype while keeping its own size; no data is transferred. A subsequent device-to-device copy between target and ref then stays on the fast path.

Typical use: make a host→device staging buffer match a KV cache's layout so the bulk upload and the per-slot device-to-device scatter are both fast.

Parameters:

Name Type Description Default
target Tensor

The RBLN tensor whose device-allocation layout is configured.

required
ref Tensor

The device-resident RBLN tensor whose layout target adopts.

required

Raises:

Type Description
RuntimeError

if either tensor is not an RBLN tensor covering its whole storage, if the two are on different devices or have different dtypes, or if ref is not device-resident.

huge_host_empty(nbytes)

Allocate a host buffer the device can DMA into without a staging copy.

An ordinary CPU tensor is 64 B aligned; the runtime's copy path stages any host address that is not page aligned through a bounce buffer, and even an aligned one pays a page fault per 4 KiB the first time the runtime resolves its host addresses, a cost that lands in the transfer, not in setup. This returns 2 MiB-aligned memory instead, prefaulted, so neither happens. It also asks for transparent huge pages, but that part is best effort: with THP disabled the alignment still holds and nothing is huge-page backed.

The buffer is released when the last reference to the returned tensor (or to a view of it) goes away.

Parameters:

Name Type Description Default
nbytes int

Size of the buffer in bytes. Must be in 1..sys.maxsize.

required

Returns:

Type Description
Tensor

torch.Tensor: A zero-filled 1-D uint8 CPU tensor of nbytes bytes, sharing the buffer's memory rather than copying it.

Raises:

Type Description
TypeError

if nbytes is not an integer.

ValueError

if nbytes is outside 1..sys.maxsize.

MemoryError

if the allocation fails.

Example
slab = torch.rbln.huge_host_empty(1 << 30)
slab.view(...)  # hand to whatever consumes the host side

offload()

Context manager that enables RBLN file offloading for its scope.

Inside the with block, the process-wide file offloading switch is on, so host-side regions backing RBLN tensors allocated within the block may be paged out to disk. Use this around code paths that allocate large host-resident tensors (for example, KV-cache initialization) where host RAM pressure matters.

Nested offload blocks are tracked via a thread-safe depth counter; the switch is flipped back off only when the outermost context exits.

Example
with torch.rbln.offload():
    tensor = torch.zeros(1 << 30, device="rbln:0")  # offloaded

release_offload_temp_storage()

Remove this process's file offloading temp files and directories.

offload() writes into a per-process directory under RBLN_OFFLOAD_DIR (default $HOME/.cache/rbln_cache/offload) that the runtime removes on teardown. Call this on a shutdown path that may be killed first. Offloaded tensors must not be used afterwards.

Returns:

Name Type Description
int int

The number of temp files removed.

Explain과 프로파일링

torch.rbln.explain()은 실행 시간을 측정하는 프로파일러가 아니라 숨은 오버헤드를 설명하는 도구입니다. 지정한 영역의 호스트 왕복 전송, CPU fallback, 재컴파일을 집계하고 각각의 원인을 표시합니다. 실제 경과 시간은 torch.profiler로 측정해야 합니다. Rebel100™ NPU에서는 런타임을 시작하기 전에 RBLN_PROFILER=1을 설정하면 Kineto 브리지가 RBLN 디바이스 활동을 트레이스에 전달합니다. ATOM™ NPU에서는 브리지가 비활성 상태로 유지되며 호스트 활동만 표시됩니다(환경 변수 › 프로파일링 참고).

API 반환값 요약
torch.rbln.explain(with_stack=False) RBLNExplain 지정한 영역을 감싸는 컨텍스트 관리자입니다. with_stack=True이면 연산자별 첫 fallback, 재컴파일, 호스트 왕복 전송의 Python 호출 위치를 기록합니다. trace=는 더 이상 권장하지 않는 with_stack=의 별칭입니다.
torch.rbln.explain_steady(fn, *, warmup=2, return_cold=False, as_diff=False, with_stack=False) RBLNExplain, (cold, warm), 또는 RBLNDiff 한 영역 안에서 fn을 한 번 호출하고 warmup회 더 호출한 뒤 두 번째 영역 안에서 한 번 더 호출하여 첫 호출 비용과 정상 상태를 구분합니다. fn을 이전에 실행하지 않았으며 매 호출 같은 작업을 한다고 가정합니다. as_diff=True이면 신호별 변화를 반환합니다.
RBLNExplain.report() str 마커로 시작하는 보고서입니다. [clean] 또는 [overhead: N signals], Count, Bytes, Note 열의 신호 표, 신호별 상세 블록을 포함합니다.
RBLNExplain.verdict() dict clean 플래그와 reasons를 반환하며 CI 판정에 사용할 수 있습니다.
RBLNExplain.dump() dict 모든 신호를 원시 수치로 반환합니다.
RBLNExplain.help(signal=None) str 특정 신호 또는 발생한 모든 신호의 전체 설명을 반환합니다.
RBLNExplain.diff(other) RBLNDiff 지정한 두 영역을 비교합니다.
RBLNExplain.start() / stop() — with 대신 영역의 시작과 끝을 직접 지정합니다.
torch.rbln.profile, torch.rbln.RBLNProfile 별칭 이전 코드와 호환되도록 남겨 둔 explain과 RBLNExplain의 별칭입니다.

보고하는 신호는 다음과 같습니다.

신호 의미 일반적인 안내
host_bounce/* 디바이스 간 경로 대신 호스트 왕복 전송(디바이스 → 호스트 → 디바이스)을 사용한 복사입니다. Bytes는 호스트 경로의 전송량이며 >> physical d2h 행은 디바이스 경계를 넘은 바이트가 있는지 표시합니다. 텐서를 연속 형태로 만들거나 디바이스 간 복사 경로 사용
runtime/v2v_slow 디바이스 간 복사에 느린 경로를 사용했습니다. 로드한 librbln.so가 런타임 카운터를 제공할 때만 관찰할 수 있습니다. set_device_layout_like로 레이아웃 맞춤
dispatch/cpu_fallback CPU에서 실행한 연산자를 연산자별 횟수와 why: 행(dtype-not-fp16, nan/inf input, all-scalar inputs), 빠른 경로 핸들러가 없는 연산자 목록으로 표시합니다. 디바이스 커널이 없는 연산자와 CPU에 고정된 연산자는 집계하지 않지만 fallback 로그에는 이름을 표시합니다. 지원하는 dtype 사용 또는 torch.compile로 실행
dispatch/recompile 영역 안에서 연산자나 그래프를 다시 컴파일했습니다. shape와 dtype을 일정하게 유지

보고서 머리글에는 영역의 경과 시간, 디바이스 예약 메모리의 최댓값, 호출 유형별 런타임 내부 소요 시간도 표시합니다. 프로세스의 스레드 수가 CPU 코어 수보다 많으면 경고를 표시합니다.

보고서를 해석할 때는 다음 세 가지 규칙을 따라야 합니다.

  • 한 번에 하나의 영역만 사용해야 합니다. 영역은 중첩되거나 겹치면 안 되며 하나의 스레드에서 유지해야 합니다. 두 번째 영역을 열면 예외가 발생합니다.
  • 컴파일된 순전파만 감싸지 말고 단계 전체를 감싸야 합니다. 컴파일된 그래프는 구조상 clean이며 숨은 작업은 그래프 주변의 eager 코드에 있습니다.
  • ! host oversubscription 행은 프로세스의 스레드 수가 코어 수보다 많다는 뜻입니다. 이 경우 영역 안의 호스트 지연은 개별 연산자보다 경합 때문에 발생할 수 있습니다. 연산자별 수치를 읽기 전에 affinity나 OMP_NUM_THREADS를 조정해야 합니다. 머리글에 런타임 신호가 노출되지 않는다고 표시되면 runtime/v2v_slow 행이 없더라도 빠른 경로를 사용했다는 근거가 되지 않습니다.

RBLNExplain

A hidden-overhead explain region. Create one with explain() and use it as a context manager.

Regions must not overlap: the underlying counters and timers are process-global, so opening a nested or concurrent region raises a RuntimeError. The counters are also process-wide, meaning the values include activity from every thread that ran during the region, not only the calling thread.

report()

Render the human-readable report: a [clean] / [overhead: N signals] marker, a torch.profiler-style signal table with a Note column carrying the remedy for each actionable row, and per-signal detail blocks.

Returns:

Name Type Description
str str

The report text. Print this.

verdict()

Summarize the region as a clean flag plus the factual reasons behind it.

The result is intended for CI gating. clean states whether any hidden signal fired; it is not a severity grade.

Returns:

Type Description
Dict[str, Any]

Dict[str, Any]: A dictionary containing clean and reasons, among others.

dump()

Return every signal as raw numbers, for programmatic checks.

Returns:

Type Description
Dict[str, Any]

Dict[str, Any]: Host-bounce counts and bytes by site, dispatch counters (CPU fallbacks, recompilations, warm hits), per-operator breakdowns, runtime residency, and the region wall time.

start()

Open the region manually instead of entering with. Returns self.

stop()

Close a region opened with start(). Returns self.

help(signal=None)

Return the full remedy text for the signals that fired in the region.

Parameters:

Name Type Description Default
signal Optional[str]

A signal name, either the bare cause or the report label such as dispatch/cpu_fallback. Without it, the text covers every signal that fired. Defaults to None.

None

Returns:

Name Type Description
str str

The remedy text.

diff(other)

Compare this region with a later one, for example a first call against a steady-state call. A region records only what happened inside it, so it cannot separate one-time cost from recurring cost by itself; placing two regions is how that structure is supplied. See RBLNDiff.

Parameters:

Name Type Description Default
other RBLNExplain

The later region. The comparison runs from self to other.

required

Returns:

Name Type Description
RBLNDiff RBLNDiff

The signal-by-signal change between the two regions.

RBLNDiff(a, b)

The signal-by-signal change between two regions, from a to b.

A region records only what happened inside it, so on its own it cannot separate a one-time cost from a recurring one. Placing the two regions, for example around a first call and a later steady-state call, supplies that structure. The diff reports only what changed between the two points: a signal that is zero in b did not recur, and a signal that persists is overhead that recurs between them. It makes no claim about anything outside the two regions.

Build the diff of two closed regions a and b; RBLNExplain.diff() calls this.

dump()

Return the diff as raw numbers.

The dictionary has the following shape:

1
2
3
4
5
6
7
8
{
    "signals": {name: {"a": int, "b": int, "a_bytes": int, "b_bytes": int}},
    "persists": [name, ...],   # present in b: the recurring, actionable set
    "gone": [name, ...],       # present in a only
    "appeared": [name, ...],   # present in b only
    "persists_by_op": [{"signal": ..., "op": ..., "count": ..., "at": ...}],
    "device_memory": {...},
}

a_bytes and b_bytes are present for byte-carrying signals only, so a recurring cost can be ranked by host-traffic volume as well as by count.

Returns:

Type Description
dict[str, Any]

dict[str, Any]: The diff as a dictionary.

report()

Human-readable diff table with one row per signal and a >> persists marker on the recurring ones.

explain(with_stack=False, *, trace=None)

Return a hidden-overhead explain region, usable as a context manager.

A normal PyTorch operation can silently round-trip the host (NPU to CPU to NPU), fall back to a CPU kernel, or trigger a recompilation. None of that is visible in your Python code. explain() counts those hidden events, attributes a cause and a remedy to each, and renders a torch.profiler-style report.

This is a hidden-overhead explainer, not a timing profiler: it does not report how long a forward pass took or which layer is slow. A region with no hidden overhead can still be slow because it is device-compute bound. For wall-clock timing, use torch.profiler.

Parameters:

Name Type Description Default
with_stack bool

If True, capture the Python call site of each fallback, recompilation, and host bounce (deduplicated per operator) and show it in the report. Off by default, so a plain region adds nothing to any code path. Defaults to False.

False

Returns:

Name Type Description
RBLNExplain RBLNExplain

A region object usable as a context manager.

Example
1
2
3
4
5
6
with torch.rbln.explain() as p:
    model(x)

print(p.report())  # [clean] / [overhead] marker plus a signal table
p.verdict()        # {'clean': bool, 'reasons': [...]} for CI gating
p.dump()           # every signal as raw numbers
Note

torch.rbln.profile and torch.rbln.RBLNProfile are backward-compatible aliases of explain and RBLNExplain. The trace= keyword is a deprecated alias for with_stack=.

explain_steady(fn, *, warmup=2, return_cold=False, as_diff=False, with_stack=False, trace=None)

Place two explain regions around fn: one around the first call it makes and one around a later call after warmup more calls.

The helper only automates region placement. Its cold and warm labels mean the first call it made and a later call it made, nothing more. Reading the result as one-time versus recurring cost rests on two assumptions that the caller has to guarantee, because the helper cannot verify them:

  1. fn was not run or compiled before this call. Otherwise the one-time cost happened before the cold sample and is not captured.
  2. Every fn() call does the same work. Otherwise the recompiles in the warm sample come from different shapes, not from recurring overhead.

When both hold, cold.diff(warm) shows what changed: signals gone in the warm region did not recur across the two calls, and signals that persist are the recurring overhead. The helper is plain Python orchestration and adds nothing to the hot path.

Parameters:

Name Type Description Default
fn Callable[[], Any]

The callable to observe. It is called warmup + 2 times in total.

required
warmup int

Number of calls between the two regions. Defaults to 2.

2
return_cold bool

Return (cold, warm) instead of the warm region alone. Defaults to False.

False
as_diff bool

Return cold.diff(warm), the signal-by-signal change, instead of a region. Defaults to False.

False
with_stack bool

Record the first Python call site per operator in both regions. Defaults to False.

False
trace Optional[bool]

Deprecated alias for with_stack. Defaults to None.

None

Returns:

Type Description
RBLNExplain | tuple[RBLNExplain, RBLNExplain] | RBLNDiff

RBLNExplain | tuple[RBLNExplain, RBLNExplain] | RBLNDiff: The warm region by default; (cold, warm) with return_cold=True; the RBLNDiff with as_diff=True.

Example
d = torch.rbln.explain_steady(lambda: model(x), warmup=2, as_diff=True)
print(d.report())  # signals marked as persisting recur across the two calls

컴파일된 프로그램

torch.compile은 백엔드가 반환한 callable을 Dynamo 코드 캐시에 보관하므로 사용자 코드는 컴파일 결과의 핸들을 직접 받지 못합니다. torch.rbln.capture_programs()는 열린 범위 안에서 rbln 백엔드가 만드는 모든 프로그램을 빌드 순서로 기록합니다. torch.profiler.profile()이 범위 안의 이벤트를 수집하는 것과 같은 방식입니다. 캡처한 각 프로그램은 입력과 출력을 설명하며 동적 shape 텐서의 디바이스 레이아웃도 포함합니다.

1
2
3
4
5
6
7
8
9
with torch.rbln.capture_programs() as programs:
    compiled = torch.compile(model, backend="rbln")
    compiled(*warmup_inputs)  # Dynamo가 여기서 그래프를 빌드합니다.

for program in programs:
    print(program.name, program.device)
    for spec in program.input_specs:
        if spec.physical_placement is not None:
            print(spec.name, spec.physical_placement.shards)
API 요약
torch.rbln.capture_programs() list[CompiledProgram]을 제공하는 컨텍스트 관리자이며 torch.compile이 백엔드를 호출할 때 목록을 채웁니다. 중첩 범위는 각각 열려 있는 동안 빌드한 모든 프로그램을 받습니다. 범위는 thread-local이므로 연 스레드에서 수행한 컴파일만 기록합니다.
torch.rbln.CompiledProgram 컴파일된 그래프 하나입니다. name(예: "0/0"인 Dynamo 컴파일 ID), device, runtime(callable의 실행 핸들), input_specs, output_specs를 포함합니다.
torch.rbln.InputSpec, torch.rbln.OutputSpec 입력 또는 출력 하나입니다. shape, dtype, physical_placement를 포함하며 입력에는 name도 있습니다. 런타임이 입력을 받고 출력을 반환하는 순서대로 나열합니다.
torch.rbln.PhysicalPlacement 동적 shape 입력 또는 출력의 디바이스 레이아웃입니다. 물리 shape, dtype, shards를 포함합니다. 정적 shape 입력과 출력에서는 None입니다.
torch.rbln.ShardPlacement 해당 레이아웃의 shard 하나입니다. node_id, chiplet_id, slice_shape를 포함합니다.

이 클래스들은 RBLN Compiler에 구현되어 있으며 처음 접근할 때 로드됩니다. import torch만으로는 컴파일러를 로드하지 않습니다. 현재 torch-rbln 릴리스와 짝을 이루는 rebel-compiler 릴리스가 필요합니다(설치 참고).

CompiledProgram(name, device, runtime, input_specs, output_specs) dataclass

One graph the rbln backend built for torch.compile.

Attributes:

Name Type Description
name str

Dynamo's compile id for the graph ("0/0", "0/1", ...); empty if the backend ran outside a Dynamo compile.

device Optional[device]

The logical RBLN device the graph's input tensors live on, where the runtime allocates its outputs; None when no input is an RBLN tensor.

runtime Any

The execution handle behind the compiled callable.

input_specs Tuple[InputSpec, ...]

The graph's inputs, in the order the runtime takes them.

output_specs Tuple[OutputSpec, ...]

The graph's outputs, in the order the runtime returns them.

InputSpec(name, shape, dtype, physical_placement=None) dataclass

An input of a compiled program.

Attributes:

Name Type Description
name str

The input's name in the compiled model; may be empty.

shape Tuple[int, ...]

The compiled extents.

dtype dtype or dtype

The element type.

physical_placement Optional[PhysicalPlacement]

The device layout of a dynamic-shape input; None for a static one.

OutputSpec(shape, dtype, physical_placement=None) dataclass

An output of a compiled program. The fields read as in InputSpec.

Attributes:

Name Type Description
shape Tuple[int, ...]

The compiled extents.

dtype dtype or dtype

The element type.

physical_placement Optional[PhysicalPlacement]

The device layout of a dynamic-shape output; None for a static one.

PhysicalPlacement(shape, dtype, shards) dataclass

Device layout of a dynamic-shape input or output: its physical shape, dtype, and the shards it is split into.

A static dimension is a plain int. A dynamic dimension is an expression written as nested tuples: ("symbol", name) is the dynamic-shape variable name, whose value is the size of the input dimension compiled as dynamic; ("prod", e1, e2, ...) and ("sum", e1, e2, ...) are the product and sum of their operands. Binding the variables to the current input sizes gives the concrete extent: [2, ("symbol", "s0"), 8] with s0 == 4 is [2, 4, 8]. The dynamic axis is never split across shards, so it appears as the same symbol in shape and in every shard's slice_shape.

Attributes:

Name Type Description
shape tuple

The physical shape on the device.

dtype str

The element type on the device.

shards Tuple[ShardPlacement, ...]

The shards the tensor is split into.

ShardPlacement(node_id, chiplet_id, slice_shape) dataclass

One device shard of a tensor: which (node, chiplet) holds it and the extent it holds.

Attributes:

Name Type Description
node_id int

The node that holds the shard.

chiplet_id int

The chiplet that holds the shard.

slice_shape tuple

The extent of the shard, one entry per dimension. A static dimension is an int; a dynamic dimension is an expression over the model's dynamic-shape variables (see PhysicalPlacement).

capture_programs()

Context manager that records the programs the rbln backend builds inside it.

torch.compile keeps the callable a backend returns inside Dynamo's code cache, so the caller never receives a handle to what was compiled. This scope yields a list that fills, in build order, as torch.compile invokes the backend, the way torch.profiler.profile() collects the events inside it.

Every open scope receives each program, so nested scopes see the same programs; an inner scope simply sees fewer. The scope is thread-local: it records the backend calls made from the thread that opened it.

Returns:

Type Description
Iterator[List[CompiledProgram]]

Iterator[List[CompiledProgram]]: The list of captured programs, as the with target.

Example
1
2
3
4
5
6
7
8
9
with torch.rbln.capture_programs() as programs:
    compiled = torch.compile(model, backend="rbln")
    compiled(*warmup_inputs)  # Dynamo builds the graphs here

for program in programs:
    print(program.name, program.device)
    for spec in program.input_specs:
        if spec.physical_placement is not None:
            print(spec.name, spec.physical_placement.shards)

진단

명령 요약
python -m torch_rbln.diagnose 라이브러리 검색 경로, 패키지 위치, 모든 librbln.so 후보와 실제 로드한 라이브러리, rebel ABI 판정 결과를 출력합니다.

지원 연산

eager 실행에서 연산자는 두 가지 구현 경로로 RBLN NPU에 도달합니다. 다음 표는 각 연산자를 개별적으로 디스패치하는 eager 실행의 지원 범위를 설명합니다. torch.compile(backend="rbln")로 컴파일한 그래프 안의 지원 범위는 RBLN Compiler가 결정하며, 지원하는 연산 - 파이토치에 정리되어 있습니다.

경로 실행 방식 목록 출처
컴파일 커널 첫 사용 시 RBLN Compiler가 연산자의 shape와 dtype에 맞춰 컴파일하고 캐시에 저장합니다. 바인딩은 빌드 시 aten/src/ATen/native/native_functions.yaml에서 생성합니다. native_functions.yaml(dispatch: PrivateUse1)
네이티브 커널 libtorch_rbln.so의 C++ 커널이 런타임을 통해 복사, 뷰, 인덱싱 연산을 직접 수행합니다. 컴파일하지 않습니다. aten/src/ATen/native/RBLNRegisterOps.cpp

Dtype 정책

Dtype 컴파일 커널 네이티브 커널
float16, bfloat16 디바이스에서 실행 디바이스에서 실행
float32, 정수, bool, 기타 CPU fallback 디바이스에서 실행(복사, 뷰, 인덱싱은 dtype에 의존하지 않음)

Scaled dot-product attention도 같은 두 디바이스 dtype을 사용합니다. 이번 릴리스에는 autocast dtype이 등록되지 않아 torch.autocast는 rbln에 적용되지 않습니다. 혼합 dtype 입력의 타입 승격 결과가 디바이스 dtype 범위를 벗어나면 CPU로 fallback합니다.

컴파일 연산자

다음 연산자는 NPU 커널로 실행됩니다. 지원하는 입력 조건과 제한 사항은 비고에 표시합니다.

연산자 Torch API 비고
aten::abs torch.abs
aten::add torch.add, + alpha 지원
aten::sub torch.sub, - alpha 지원
aten::mul torch.mul, *
aten::div torch.div, /
aten::neg torch.neg, 단항 -
aten::pow torch.pow, ** 스칼라 지수만 지원. 텐서 지수 또는 스칼라 밑은 CPU에 고정
aten::rsqrt torch.rsqrt
aten::log torch.log
aten::ceil torch.ceil
aten::floor torch.floor
aten::clamp torch.clamp 스칼라 경계값 지원. 텐서 경계값은 CPU에 고정
aten::sigmoid torch.sigmoid
aten::silu torch.nn.functional.silu
aten::_softmax torch.softmax, torch.nn.functional.softmax
aten::mm torch.mm, @
aten::bmm torch.bmm
aten::addmm torch.addmm
aten::linear torch.nn.functional.linear, torch.nn.Linear
aten::mean torch.mean
aten::max, aten::min torch.max, torch.min 전체 축약 연산 지원. dim 축약 연산은 CPU에 고정
aten::maximum, aten::minimum torch.maximum, torch.minimum
aten::eq, ne, lt, le, gt, ge 비교 연산자
aten::logical_not torch.logical_not
aten::where torch.where
aten::masked_fill_ Tensor.masked_fill_, torch.masked_fill
aten::_scaled_dot_product_fused_attention_overrideable torch.nn.functional.scaled_dot_product_attention rbln 텐서에서 _fused_sdp_choice가 선택

네이티브 연산자

이 연산자들은 libtorch_rbln.so의 C++ 커널에서 런타임을 직접 호출합니다. 계산하는 대신 데이터를 이동하거나 설명하므로 모든 dtype에서 실행됩니다.

그룹 연산자
할당과 채우기 empty, empty_strided, zero_, fill_(스칼라 값), clone, _efficientzerotensor, arange
복사 _copy_from, _copy_from_and_resize, _foreach_copy_, resize_, set_, _local_scalar_dense(.item())
뷰(메타데이터만 변경, 디바이스 작업 없음) view, _unsafe_view, _reshape_alias, as_strided, alias, unfold
연결과 반복 cat(cat으로 분해되는 stack 포함), repeat_interleave
인덱싱 index_select, index_copy, 하나의 축에 정수 텐서 인덱스 하나를 사용하는 index(다른 형태는 커널 내부에서 CPU로 fallback)

strided 뷰의 디바이스 간 copy_는 디바이스에서 처리합니다. 두 디바이스 경로와 호스트를 거치는 한 가지 경우는 실행 방식 › 뷰와 strided 복사에서 설명합니다.

CPU에 고정된 연산자

다음 연산자들은 CPU fallback 경로에 명시적으로 등록되어 있습니다. 디바이스에서 호스트로 복사한 뒤 호스트에서 실행하고 결과를 다시 디바이스로 복사합니다. 다른 fallback과 마찬가지로 INFO 수준의 로그를 남깁니다. 등록 자체가 없는 연산자만 제어하는 TORCH_RBLN_DISABLE_FALLBACK=unsupported_op의 영향을 받지 않습니다.

그룹 연산자
난수 생성 uniform_, normal_, normal, random_, randperm, native_dropout
원소별 연산 sin, cos, exp, trunc, sign, sgn, signbit, relu, addcmul, fmod, clamp(텐서 경계값), pow(스칼라 밑 또는 텐서 지수), nan_to_num, isnan, isposinf, isneginf, isin, equal
비트 및 논리 연산 bitwise_and, bitwise_or, bitwise_xor, bitwise_not, logical_and, logical_or, logical_xor
축약과 스캔 sum(dim 목록), all, any, cumsum, count_nonzero, linalg_vector_norm, argmax, max.dim, min.dim, topk
인덱싱과 scatter gather, scatter, index_add, index_fill_, _index_put_impl_, put_, masked_scatter_, masked_select, nonzero, fill_(텐서 값)
Shape flip, tril, triu, view_as_real
정규화 native_batch_norm
선형대수 _linalg_svd

모델에서 자주 실행하는 경로에 CPU 고정 연산자가 있다면 디바이스 커널 구현 후보가 됩니다. 문제 보고를 통해 알려 주시기 바랍니다. 일부 연산자에는 이미 일반 boxed 디스패처를 생략하는 빠른 호스트 경로가 있습니다(정수 원소별 연산, 마지막 차원의 fp32 mean, fp32 pow(x, 2), fp32 rsqrt). fp32로 계산하는 RMSNorm 분산의 비용은 일반 fallback보다 작습니다.

표에 없는 연산자

  • 복합 연산자인 torch.stack 등은 앞의 연산자로 분해되며(stack → cat) 해당 경로를 따릅니다.
  • 여러 인덱스 텐서를 사용하는 고급 인덱싱(t[:, idx_a, :, idx_b])은 네이티브 index 커널의 지원 범위에 포함되지 않으며 CPU에서 실행됩니다.
  • 비연속 out= 텐서는 연속 버퍼에서 처리한 뒤 다시 복사하므로 디바이스 메모리 할당과 복사가 한 번씩 추가됩니다. 자주 실행하는 경로에는 연속 out=을 전달하는 것을 권장합니다.
  • torch.ops.rbln_custom_ops의 사용자 정의 연산자(paged attention 커널)는 RBLN vLLM 네이티브 경로의 내부 구현이며 공개 API가 아닙니다.

관련 문서

  • 실행 방식 - dtype 정책, 지연 메모리 할당, eager 디스패치, CPU fallback
  • 환경 변수 - 이 API의 동작을 제어하는 설정
  • 문제 해결 - fallback 로그와 진단 출력 읽기