앞서 작성한 글들에서 mlx-ml 은 불안정 해서 사용하지 못하고 있다는 내용을 작성한적 있습니다. 그래도 일단 애플 하드웨어에서 mlx의 성능차이가 궁금하신 분들이 계실겁니다. 몇몇 분은 데이터좀 알려달라고 하시기도 했구요 ..
일단 허깅페이스의 mlx커뮤니티에서 Qwen3-Coder-Next-4bit 라는 모델을 hf download 명령으로 다운로드 받았습니다.
https://huggingface.co/mlx-community/Qwen3-Coder-Next-4bit
hf download mlx-community/Qwen3-Coder-Next-4bitQwen/Qwen3-Coder-Next 모델을 mlx 로 변환한 모델입니다. 파일크기는 44.8기가 정도이구요.
앞서 ollama 에서 gguf 모델을 사용한 결과가 ..
pirogom@pirogom-Mac-Studio Desktop % ollama run qwen3-coder-next:q4_K_M "hi" --verbose
Hello! 😊 How can I help you today?
total duration: 999.43025ms
load duration: 64.577209ms
prompt eval count: 9 token(s)
prompt eval duration: 614.886875ms
prompt eval rate: 14.64 tokens/s
eval count: 12 token(s)
eval duration: 317.202626ms
eval rate: 37.83 tokens/sq4_K_M 양자화 모델에 hi를 때린 결과가 대충 37.83 tokens/s 정도 나왔습니다.
from mlx_lm import load, generate
model, tokenizer = load("mlx-community/Qwen3-Coder-Next-4bit")
prompt = "hi"
if tokenizer.chat_template is not None:
messages = [{"role": "user", "content": prompt}]
prompt = tokenizer.apply_chat_template(
messages, add_generation_prompt=True, return_dict=False,
)
response = generate(model, tokenizer, prompt=prompt, verbose=True)이런 코드를 작성해서 실행해 봅니다.
pirogom@pirogom-Mac-Studio TestCode % python test1.py
Fetching 17 files: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 17/17 [00:00<00:00, 152032.34it/s]
Download complete: : 0.00B [00:00, ?B/s] | 0/17 [00:00<?, ?it/s]
==========
mx.metal.device_info is deprecated and will be removed in a future version. Use mx.device_info instead.
Hello! How can I help you today? 😊
==========
Prompt: 9 tokens, 132.078 tokens-per-sec
Generation: 12 tokens, 83.487 tokens-per-sec
Peak memory: 44.904 GB피크 메모리는 44기가 정도.. 83 tokens/s 정도 나왔네요. 확실히 mlx를 사용 않는 gguf 모델의 ollama 보다 속도는 빠르긴 합니다. 물론 라이브러리를 호출해서 직졉 결과를 뽑아내는거랑 api 백엔드를 거쳐서 동작하는거랑 동작구조의 차이는 있겠습니다만..
그럼에도 불구하고 어쨋든 그냥 metal gpu 가속만을 받는 것과 mlx를 통해 메모리 제어에 추가 이점을 가져가는 것의 차이는 있긴 할겁니다.
from mlx_lm import load, generate
model, tokenizer = load("mlx-community/Qwen3-Coder-Next-4bit")
prompt = "간단한 숫자야구 게임을 go언어로 작성해줘"
if tokenizer.chat_template is not None:
messages = [{"role": "user", "content": prompt}]
prompt = tokenizer.apply_chat_template(
messages, add_generation_prompt=True, return_dict=False,
)
response = generate(model, tokenizer, prompt=prompt, max_tokens=32768, verbose=True)이제 앞서 ollama 에서도 “간단한 숫자야구 게임을 go언어로 작성해줘”라는 짓을 해봤으니 같은 짓을 해봅니다.
pirogom@pirogom-Mac-Studio TestCode % python test1.py
Fetching 17 files: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████| 17/17 [00:00<00:00, 39990.56it/s]
Download complete: : 0.00B [00:00, ?B/s] | 0/17 [00:00<?, ?it/s]
==========
mx.metal.device_info is deprecated and will be removed in a future version. Use mx.device_info instead.
물론입니다! 아래는 Go 언어로 작성한 **간단한 숫자야구 게임**입니다.
규칙은 다음과 같습니다:
- 1부터 9까지의 중복되지 않는 **3자리 숫자**를 랜덤으로 생성합니다.
- 사용자가 숫자를 입력하면, **스트라이크**(위치와 숫자가 일치)와 **볼**(숫자는 일치하지만 위치가 다름)를 알려줍니다.
- 3스트라이크가 되면 게임이 종료됩니다.
---
### ✅ `main.go`
```go
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
func generateRandomNumber() []int {
// 1~9까지 숫자를 담은 슬라이스 생성
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
// 섞기 (Fisher-Yates shuffle)
rand.Seed(time.Now().UnixNano())
for i := len(numbers) - 1; i > 0; i-- {
j := rand.Intn(i + 1)
numbers[i], numbers[j] = numbers[j], numbers[i]
}
// 처음 3개만 사용
return numbers[:3]
}
func checkGuess(guess, answer []int) (strike, ball int) {
for i := 0; i < len(guess); i++ {
for j := 0; j < len(answer); j++ {
if guess[i] == answer[j] {
if i == j {
strike++
} else {
ball++
}
}
}
}
return
}
func main() {
fmt.Println("=== 숫자야구 게임 ===")
fmt.Println("1~9까지의 중복되지 않는 3자리 숫자를 입력하세요.")
fmt.Println("예: 123, 456 등")
answer := generateRandomNumber()
// fmt.Println("정답 (디버깅용):", answer) // 디버깅 시 주석 해제
scanner := bufio.NewScanner(os.Stdin)
attempts := 0
for {
fmt.Print("입력: ")
if !scanner.Scan() {
fmt.Println("\n게임을 종료합니다.")
break
}
input := strings.TrimSpace(scanner.Text())
// 유효성 검사
if len(input) != 3 {
fmt.Println("3자리 숫자를 입력해주세요.")
continue
}
guess := make([]int, 3)
valid := true
seen := make(map[int]bool)
for i, ch := range input {
digit, err := strconv.Atoi(string(ch))
if err != nil || digit < 1 || digit > 9 {
fmt.Println("1~9 사이의 숫자만 입력해주세요.")
valid = false
break
}
if seen[digit] {
fmt.Println("중복된 숫자는 입력할 수 없습니다.")
valid = false
break
}
seen[digit] = true
guess[i] = digit
}
if !valid {
continue
}
strike, ball := checkGuess(guess, answer)
attempts++
fmt.Printf("결과: %d 스트라이크, %d 볼\n", strike, ball)
if strike == 3 {
fmt.Printf("🎉 정답입니다! %d번 만에 맞추셨습니다.\n", attempts)
break
}
}
}
```
---
### 📌 실행 방법
1. 위 코드를 `main.go` 파일로 저장합니다.
2. 터미널에서 다음 명령어로 실행:
```bash
go run main.go
```
---
### 🎮 예시 실행 화면
```
=== 숫자야구 게임 ===
1~9까지의 중복되지 않는 3자리 숫자를 입력하세요.
예: 123, 456 등
입력: 123
결과: 0 스트라이크, 1 볼
입력: 456
결과: 1 스트라이크, 0 볼
입력: 478
결과: 2 스트라이크, 0 볼
입력: 479
🎉 정답입니다! 4번 만에 맞추셨습니다.
```
---
필요하다면 난이도 조절(자릿수 늘리기), 재시작 기능, 점수 시스템 등을 추가할 수 있어요 😊
원하시면 추가 기능도 도와드릴게요!
==========
Prompt: 25 tokens, 76.125 tokens-per-sec
Generation: 1061 tokens, 75.756 tokens-per-sec
Peak memory: 44.927 GB역시 ollama 에서 mlx 아닌 gguf 에서 보다 2배이상 빠른 속도가 나오긴 하네요 ..
단지.. 제가 제대로 사용을 못하고 있는지는 모르겠지만 .. mlx-ml은 라이브러리로 직접 쓰는건 몰라도 내장 서버기능은 문제가 좀 많아서 직접적으로 openai api 서버등으로 사용하기엔 좀 문제가 있습니다.
정확한 수치를 기록해 놓진 않아서 이렇게 결과를 뽑아놓고보니 ..
lm studio 도 다시 설치해서 속도 비교를 좀 해보긴 해야겠네요.. 제 환경에선 lm studio랑 잘 안맞는 툴들이 있었어서 ollama를 고집하고 있긴 합니다만 .. 그래도 워낙 빨리 업데이트가 일어나는 시장이니 ..
다시 한번 설치해서 확인해봐야 겠습니다.
이상입니다.