개요
MLX는 Apple 머신러닝 연구팀이 개발한 배열 프레임워크로, Apple 칩을 위해 특별히 설계되었으며 NumPy 및 PyTorch와 유사한 API를 제공합니다. 컴포저블 함수 변환, 지연 연산, 동적 그래프 구성 및 CPU와 GPU의 통합 메모리를 지원합니다. 머신러닝 모델의 효율적인 학습과 배포를 목표로 합니다.
README 미리보기
# MLX\n\n[**Quickstart**](#quickstart) | [**Installation**](#installation) |\n[**Documentation**](https://ml-explore.github.io/mlx/build/html/index.html) |\n[**Examples**](#examples)\n\n[](https://circleci.com/gh/ml-explore/mlx)\n\nMLX is an array framework for machine learning on Apple silicon,\nbrought to you by Apple machine learning research.\n\nSome key features of MLX include:\n\n- **Familiar APIs**: MLX has a Python API that closely follows NumPy. MLX\n also has fully featured C++, [C](https://github.com/ml-explore/mlx-c), and\n [Swift](https://github.com/ml-explore/mlx-swift/) APIs, which closely mirror\n the Python API. MLX has higher-level packages like `mlx.nn` and\n `mlx.optimizers` with APIs that closely follow PyTorch to simplify building\n more complex models.\n\n- **Composable function transformations**: MLX supports composable function\n transformations for automatic differentiation, automatic vectorization,\n and computation graph optimization.\n\n- **Lazy computation**: Computations in MLX are lazy. Arrays are only\n materialized when needed.\n\n- **Dynamic graph construction**: Computation graphs in MLX are constructed\n dynamically. Changing the shapes of function arguments does not trigger\n slow compilations, and debugging is simple and intuitive.\n\n- **Multi-device**: Operations can run on any of the supported devices\n (currently the CPU and the GPU).\n\n- **Unified memory**: A notable difference from MLX and other frameworks\n is the *unified memory model*. Arrays in MLX live in shared memory.\n Operations on MLX arrays can be performed on any of the supported\n device types without transferring data.\n\nMLX is designed by machine learning researchers for machine learning\nresearchers. The framework is intended to be user-friendly, but still efficient\nto train and deploy models. The design of the framework itself is also\nconceptually simple. We intend to make it easy for researchers to extend and\nimprove MLX with the
FAQ (5)
문제 해결M5 Max에서 행이 32,768을 초과하고 64의 배수가 아닐 때 sorted_indices=True로 인해 잘못된 mx.gather_qmm 결과가 나오는 문제를 어떻게 해결하나요?
MLX를 0.32.3 이상으로 업그레이드하세요. 해당 버그는 PR #3922에서 수정되었습니다:
pip install --upgrade mlx
다음 명령으로 확인하세요:
import mlx.core as mx
print(mx.__version__)
업그레이드할 수 없는 경우 sorted_indices=False를 사용하거나, 행 수를 64의 배수가 되도록 패딩한 뒤 패딩된 출력 행을 버리세요. 이 문제는 Apple M5 Max/macOS 27 환경의 MLX 0.31.2에서 발생하며, M4 Pro는 영향을 받지 않습니다.
문제 해결MLX에서 bf16 활성화를 사용할 때 mx.fast.gated_delta_update가 정밀도를 잃는 이유는 무엇이며, 어떻게 해결할 수 있나요?
mx.fast.gated_delta_update는 커널을 실행하기 전에 decay g와 beta를 q의 dtype(일반적으로 bf16)으로 캐스팅합니다. bf16은 1 바로 아래에서 1/256 간격을 가지므로, 0.9995와 같은 decay 값은 정확히 1.0으로 반올림되어, 해당 토큰에서 Gated DeltaNet 상태가 전혀 감쇠하지 않게 됩니다. 이 문제는 PR #4760에서 수정되었습니다: 이제 g와 beta는 float32로 커널에 전달되며(flash-linear-attention 및 vLLM의 동작과 일치), float64 참조 대비 출력 오차가 ~4.8e-2에서 ~2.4e-3으로 감소했습니다. 해당 수정이 포함된 MLX 버전으로 업그레이드하세요. 이전 버전에서는 유일한 해결 방법은 q, k, v도 float32로 전달하는 것이며, 이 경우 약 30% 느려집니다.
문제 해결왜 set_wired_limit를 설정했음에도 불구하고 몇 초간 유휴 상태가 지나면 MLX Metal 추론이 4–5배 느려지나요?
이 문제는 GPU가 유휴 상태가 된 직후 macOS가 MLX의 wired-memory 상주(residency)를 해제하기 때문에 발생합니다. MLX 0.32.x는 상주를 한 번만 요청하고 갱신하지 않습니다. 하트비트를 사용해 상주를 다시 요청하는 PR #4633이 포함된 릴리스로 MLX를 업그레이드하면 수정됩니다. 임시 해결 방법으로 다음을 실행하세요:
sudo sysctl iogpu.disable_wired_collector=1
다음 명령으로 확인하세요:
sysctl iogpu.disable_wired_collector
이 설정은 재부팅 후 초기화됩니다. 또는 약 1초에 한 번씩 아주 작은 MLX 연산으로 GPU를 활성 상태로 유지하세요. 테스트에서는 3초 간격으로는 충분하지 않았습니다. 이 문제는 Ollama의 Apple Silicon MLX 러너를 포함하여 macOS 26+의 MLX 0.32.x에 영향을 줍니다.
문제 해결macOS 14를 타겟으로 할 때 Apple Silicon에서 잘못된 MLX CPU Float16 sigmoid 또는 비교 결과를 어떻게 수정하나요?
이 문제는 MLX issue #4601로 인해 발생합니다: Float16 NEON 비교 폴백이 lane 0만 읽은 뒤 해당 마스크를 모든 lane에 브로드캐스트하기 때문입니다. mlx/backend/cpu/simd/neon_fp16_simd.h에서 return Simd<uint16_t, N>(*(uint16_t*)(&out));와 같은 코드는 전체 NEON 벡터를 유지하도록 수정해야 하며, 일반적으로 return Simd<uint16_t, N>(out); 형태로 변경합니다. 이 변경 사항을 모든 Float16 비교 오버로드와 논리 부정 오버로드에 적용한 다음, MLX와 대상 타깃을 클린 리빌드하십시오. 수정 후 리프로듀서는 0.268799 대신 예상값 0.731059에 가까운 sigmoid(1) = 0.731445를 보고합니다. 즉시 패치할 수 없는 경우에는 Float32로 활성화 값을 계산한 뒤 다시 캐스팅하십시오. 예를 들어 sigmoid(x.astype(float32)).astype(float16)처럼 하거나, 업스트림 수정이 포함된 MLX 릴리스를 사용하십시오.
문제 해결MLX에서 큰 텐서의 마지막이 아닌 축을 축소할 때 mx.sum이 전부 0을 반환하는 문제를 해결하는 방법은?
이 문제는 MLX의 column/non-last-axis reduction 커널에서 발생하는 32비트 Metal grid overflow 때문에 발생합니다. 내부 reduction stride가 2^29인 경우, launch 크기가 256 * ceil(2^29 / 32) = 2^32가 되어 dispatch 차원이 overflow되면서 출력이 0이 되거나 부분적으로 0이 됩니다. MLX 0.32.0.dev20260609+cc3f3e60에서 (1, 32, 4096, 131072)와 같은 shape에 대한 mx.sum(x, axis=1)에 영향을 미칩니다. last-axis reduction은 다른 코드 경로를 사용하므로 정상적으로 동작합니다.
즉각적인 해결 방법: 축소할 축을 마지막 축으로 이동한 뒤 해당 위치에서 reduction을 수행하세요:
y = mx.sum(mx.moveaxis(x, 1, -1), axis=-1)
mx.eval(y)
임의의 축에 대해서는:
y = mx.sum(mx.moveaxis(x, axis, -1), axis=-1)
또는 슬라이스를 명시적으로 더할 수도 있습니다:
y = None
for i in range(x.shape[1]):
block = x[:, i:i+1]
y = block if y is None else y + block
mx.eval(y)
영구적인 해결 방법: issue #3784에 대한 "Fix Metal column reduction grid overflow" 수정이 포함된 MLX 릴리스로 업그레이드하거나, 해당 PR이 포함된 커밋으로부터 MLX를 빌드하세요.