
이 프로젝트가 하는 일
이 배포 레시피는 각각 128GB의 통합 메모리를 갖춘 두 대의 NVIDIA DGX Spark에서 DeepSeek-V4.1-Flash-1017을 제공합니다. TensorFold의 네이티브 Zig 엔진을 사용하며, Spark당 하나의 랭크로 텐서 병렬화를 구성하고 포트 8888에서 OpenAI 호환 API를 노출합니다.
이 설정은 실험적인 2.9비트 EXL3 체크포인트 Mia-AiLab/DeepSeek-V4.1-Flash-1017-EXL3-EAQ-v1-2.9-bpw를 사용합니다. 모델의 대규모 컨텍스트 윈도우, 이미지 입력, 도구 호출, 선택적 사고 기능 및 체크포인트의 초안 블록을 활용하는 DSpark 추측 디코딩을 지원합니다.
저장소는 준비, Docker 이미지 빌드, 체크포인트 다운로드, 랭크 캐시 생성, 워커 설정, 서버 시작, 스모크 테스트 및 종료를 자동화합니다. 첫 번째 Spark는 헤드 역할을 하며 API를 실행하고 설정을 조정하고 랭크 0을 시작합니다. 두 번째 Spark는 랭크 1을 실행합니다.
아키텍처 및 주요 제한 사항
TensorFold는 텐서 병렬화를 2로 설정하여 BertholomusAI dsv41 제품군을 실행합니다. 두 랭크는 직접 연결된 ConnectX-7 링크를 통해 통신합니다. 헤드는 API 트래픽을 처리하고, 두 Spark는 각각 약 98GiB의 모델 가중치를 메모리에 유지합니다.
체크포인트의 크기는 약 196GiB이며 39개의 샤드로 나뉩니다. 또한 배포에는 약 203GB를 차지하는 Engram의 비양자화 테이블 2개가 필요합니다. Engram 테이블은 두 Spark의 로컬 디스크에 복사해야 합니다. 디코딩 과정에서 4KiB 단위의 무작위 읽기가 많이 발생하므로 NFS를 통해 읽으면 프리필 및 디코드 성능이 크게 저하될 수 있습니다.
이론적으로 모델은 1,048,576토큰 윈도우를 사용할 수 있지만 헤드에서 사용 가능한 메모리가 실제 제한 요소입니다. 다른 데스크톱 및 개발 서비스를 실행하는 헤드에서는 더 많은 메모리를 확보하지 않는 한 CONTEXT를 524288 이하로 유지할 것을 README에서 권장합니다.
하드웨어 및 소프트웨어 요구 사항
- 각각 128GB의 통합 메모리를 갖춘 NVIDIA DGX Spark 2대 또는 동급 GB10 시스템 2대
- ConnectX-7 포트 간 직접 QSFP 연결
- 직접 링크의 IPv4 주소, 정상적인 연결 및 RoCE v2 GID
- 두 시스템의 동일한 GPU 클록 상한. README에서는
nvidia-smi -q -d CLOCK로 클록을 확인하고 필요한 경우nvidia-smi -lgc 0,2200을 사용할 것을 권장합니다. - 헤드에서 워커로 접속할 수 있는 키 기반 SSH
- 두 시스템에 NVIDIA 컨테이너 런타임이 설치된 Docker 및
docker그룹에 속한 사용자 - 헤드의
git,python3및 Hugging Face CLI - 체크포인트, Engram 테이블, 랭크 가중치 파일, Docker 이미지 및 캐시를 저장할 충분한 공간. 표준 구성에서는 헤드에 약 505GB, 워커에 약 310GB가 필요합니다.
직접 링크는 각 Spark에서 네트워크 장치 2개와 RoCE 장치 2개로 표시될 수 있습니다. 두 레일 모두 링크의 주소로 구성하고 양쪽 시스템에서 동일한 MTU를 사용하세요.
네트워크 및 SSH 연결 준비
ConnectX-7 인터페이스에 사설 서브넷 주소를 할당합니다. 예를 들어 README에서는 192.0.2.1/24 및 192.0.2.2/24와 같은 주소를 사용합니다. 두 시스템이 의도한 링크를 통해 서로 ping할 수 있는지 확인하세요.
헤드에서 워커용 SSH 키를 설치하고 비대화형 접속을 확인합니다.
ssh-copy-id user@<worker>
ssh -o BatchMode=yes user@<worker> true로컬 설정 파일에 워커 SSH 대상과 패브릭 주소를 설정합니다. 워커에는 이 저장소의 복사본이 필요하지 않습니다.
NFS 또는 로컬 스토리지 구성
기본적으로 워커는 NFS를 통해 헤드의 Hugging Face 캐시를 읽기 전용으로 마운트합니다. 헤드에서 NFS 서버를 설치하고 캐시를 내보냅니다.
sudo apt install nfs-kernel-server
echo "$HOME/.cache/huggingface <worker-CX7-address>(ro,no_subtree_check)" | sudo tee -a /etc/exports
sudo exportfs -ra워커에는 Ubuntu의 nfs-common과 같은 호스트용 NFS 클라이언트 도우미가 필요할 수 있습니다. 준비 스크립트는 읽기 전용 Docker NFS 볼륨을 생성하고 워커가 필요한 파일을 볼 수 있는지 확인합니다.
격리를 강화하거나 NFS를 사용하기 어려운 경우 필요한 캐시를 각 Spark에 로컬로 복사합니다. HF_CACHE를 로컬 트리로 설정하고, NFS_VOLUME을 해당 호스트 경로로 설정하고, HEAD_NFS_SERVER는 비워 두며, PREPARE=0으로 설정합니다. 로컬 캐시에는 체크포인트의 소형 파일, 비전 샤드 model-00039-of-00039, 제공할 model/ 폴더, kit, 토큰 맵 및 적절한 랭크 가중치 파일이 포함되어야 합니다.
저장소 복제 및 구성
헤드에서 저장소를 복제하고 로컬 설정 파일을 생성합니다.
git clone https://github.com/MiaAI-Lab/DeepSeek-v4.1-Flash-1017-2x-DGX-Sparks.git
cd DeepSeek-v4.1-Flash-1017-2x-DGX-Sparks
cp scripts/local.sh.example scripts/local.shscripts/local.sh를 편집하고 최소한 WORKER를 워커의 SSH 대상으로 설정합니다. 워커의 SSH 경로가 직접 패브릭 경로와 다르면 FABRIC_PEER를 워커의 ConnectX-7 주소로 설정합니다.
대부분의 설정은 scripts/config.sh에 정의되어 있습니다. 일반적인 값은 다음과 같습니다.
- 고정된 EXL3 체크포인트를 지정하는
MODEL_ID및MODEL_REVISION - 기본값이
1048576인CONTEXT - 동시 요청 4개가 기본값인
PARALLEL - Hugging Face 인증이 필요한 경우의
HF_TOKEN - 기본 모드 또는 비절제 모드를 선택하는
ABLIT
시작 전 드라이런 실행
드라이런 모드를 사용하여 변경 없이 감지된 링크와 Docker 명령을 확인합니다.
DRY_RUN=1 ./start.sh저장소는 셸 문법 검사도 수행하며, 준비 과정에서 필요한 네트워크, Docker, GPU, SSH 및 메모리 조건을 검증합니다. 구성된 최소 사용 가능 메모리인 MIN_AVAIL_GIB가 두 Spark 모두에서 확보되지 않으면 시작을 진행하지 않습니다.
두 랭크 서버 시작
헤드에서 전체 배포를 시작합니다.
./start.sh처음 실행하면 스크립트가 TensorFold 이미지를 빌드하고, 체크포인트와 Engram 테이블을 다운로드하며, RoPE 테이블과 이미지 라우팅 데이터를 준비하고, 토큰 및 랭크 파일을 생성하고, 워커의 스토리지를 구성한 다음 두 랭크를 모두 시작합니다. Zig 이미지를 빌드하는 데 Spark 한 대에서 약 6분이 걸리며, 약 24.9 GB 크기의 이미지가 생성됩니다.
시작 후 스크립트는 API가 준비될 때까지 기다린 다음 스모크 테스트를 실행합니다. 성공적으로 시작되면 DeepSeek-V4.1-Flash-1017이 8888 포트에서 실행 중이라는 메시지가 표시됩니다.
유용한 수명 주기 명령은 다음과 같습니다.
./start.sh restart
./stop.sh서빙 설정을 변경한 후에는 restart를 사용합니다. 중지 스크립트는 컨테이너를 제거하기 전에 압축 로그를 저장하며, LOG_KEEP에 따라 최신 로그를 보존합니다.
OpenAI 호환 API 호출
클라이언트는 헤드 주소에 /v1 경로를 사용하고, 정확한 모델 식별자 DeepSeek-V4.1-Flash-1017을 지정해야 합니다. 예를 들어 OpenAI 호환 Python 클라이언트는 다음과 같이 구성할 수 있습니다.
from openai import OpenAI
client = OpenAI(
base_url="http://<head-address>:8888/v1",
api_key="unused"
)
response = client.chat.completions.create(
model="DeepSeek-V4.1-Flash-1017",
messages=[
{"role": "user", "content": "Explain tensor parallelism briefly."}
],
max_tokens=512
)
print(response.choices[0].message.content)요청에서 사고 기능을 비활성화하지 않으면 모델은 답변 전에 사고 과정을 수행합니다. 추론과 최종 응답에 충분한 max_tokens를 할당하거나, 환경에서 관련 사고 및 추론 설정을 구성하세요.
텍스트, 도구, 이미지 및 긴 프롬프트 검증
저장소에는 실행 중인 엔드포인트를 확인하는 검증 유틸리티가 포함되어 있습니다.
python3 tools/validate.py http://<head-address>:8888 --model DeepSeek-V4.1-Flash-1017
API_URL=http://<head-address>:8888 python3 tools/toolcheck.py검증 모음은 텍스트, 사고 기능, 도구, 이미지 입력 및 긴 프롬프트를 다룹니다. README에 따르면 보고된 하드웨어 구성에서는 이미지 입력과 검증 도구를 완전히 확인하지 못했으므로, 해당 테스트를 보장이 아닌 배포 점검으로 간주하세요.
추가 진단을 수행하려면 랭크 로그를 확인합니다.
docker logs -f dsv41-1017-exl3-tf
ssh <worker> docker logs -f dsv41-1017-exl3-tfAbliterated 모드 사용
기본 구성은 정품 Mia EAQ 2.9-bit 체크포인트를 사용합니다. ABLIT=1을 설정하면 해당 체크포인트를 유지하면서 drowzeys/keys-DeepSeek-V4.1-Flash-1017-Abliterated의 일치하는 Keys 오버레이를 적용합니다.
이는 접근이 제한된 Hugging Face 저장소입니다. 준비하기 전에 저장소 약관에 동의하고 접근 권한이 있는 계정으로 인증하세요.
hf auth login
ABLIT=1 ./scripts/prepare.sh
ABLIT=1 ./start.sh restart또는 셸 기록에 토큰을 남기지 않고 토큰을 제공할 수 있습니다.
read -rsp 'Hugging Face read token: ' HF_TOKEN; echo
export HF_TOKEN
ABLIT=1 ./start.sh restart
unset HF_TOKEN오버레이는 ABLIT_REVISION으로 고정됩니다. 준비 과정에서는 별도의 캐시 경로와 랭크 캐시가 생성되므로 정품 데이터와 abliterated 데이터가 실수로 섞이지 않습니다. 다시 작성된 샤드는 오버레이와 랭크 파일 외에도 다른 체크포인트에 준하는 저장 공간을 요구할 수 있습니다. 다음 명령으로 정품 모드로 전환합니다.
ABLIT=0 ./start.sh restartREADME는 정품 모드의 성능 및 정확성 결과가 이 엔진에서 abliterated 모드를 검증하지 않는다고 명시합니다. 또한 준비와 시작 과정에서 동일한 ABLIT 설정을 유지하세요.
성능 및 튜닝 지침
실제 산문 및 코드 프롬프트를 사용한 측정에서 산문 스트림 하나는 약 74.9 tokens per second, 코드 스트림 하나는 109.9 tokens per second에 도달했습니다. 스트림 4개를 사용하면 총 처리량은 산문에서 약 130.0 tokens per second, 코드에서 155.5 tokens per second에 도달했습니다. 프리필 성능은 8K에서 256K 토큰까지의 프롬프트에서 약 2,000~2,180 tokens per second로 측정되었습니다.
결과는 프롬프트 내용, GPU 클록, 동시 작업, 스토리지 및 메모리 압박에 따라 달라집니다. 무작위 단어 벤치마크는 일반적인 산문이나 코드보다 초안 작성 효율이 낮으므로, 더 낮은 디코드 수치를 엔진의 일반적인 한계로 간주해서는 안 됩니다.
- 두 Spark의 로컬 디스크에 Engram 테이블을 보관하세요.
- 텐서 병렬 랭크가 반복적으로 동기화되므로 GPU 클록 상한을 일치시키세요.
- 헤드에서 다른 소프트웨어를 실행하는 경우 특히
CONTEXT를 헤드의 메모리 용량 이내로 유지하세요. - 긴 프롬프트나 여러 동시 사용자를 처리할 때는
PARALLEL을 보수적으로 설정하세요. - 네트워크 또는 배포 설정을 변경하기 전에
DRY_RUN=1을 사용하세요.
선택적 엔진 스위치 및 패치
저장소에는 zig/patches/ 아래에 엔진 패치가 포함되어 있습니다. 패치는 기본적으로 비활성화되어 있으며 start.sh를 통해 두 랭크 모두에 전달됩니다. README에 따르면 기본 이미지는 다양한 프롬프트 및 동시성 시나리오에서 동일한 토큰 해시가 생성되는지 테스트되었습니다.
TF_DS_ENGRAM_LANES=2는 Engram 읽기를 위한 두 번째 I/O 링을 활성화하지만, 측정 결과 테스트한 스토리지에서는 더 느린 것으로 나타났습니다. TF_DS_IDX_SPLIT=1은 프리필 인덱서 행을 랭크 간에 분할하지만, 테스트한 두 랭크 조합에서는 측정 가능한 성능 향상이 없었습니다. 랭크 간에 이 설정이 일치하지 않으면 두 랭크가 멈출 수 있으므로 기본적으로 비활성화되어 있습니다.
패치 0005는 프롬프트 패스 인터리빙을 개선하여 다른 긴 프롬프트를 프리페치하는 동안 기존 스트림이 디코드 라운드를 처리하도록 합니다. 동작은 PREFILL_INTERLEAVE_MS로 조정할 수 있습니다. 패치 0006은 TF_DS_IMAGE_CACHE=0을 사용해 해당 동작을 비활성화하지 않은 경우 이미지 입력의 프롬프트 상태를 보존합니다.
메모리를 모니터링하고 안전하지 않은 컨텍스트 크기를 피하세요
메모리는 운영상의 주요 제약 조건입니다. README에 따르면 다른 소프트웨어가 약 6GiB를 사용 중인 헤드에서는 512K 컨텍스트가 실용적이었지만, 655K 구성은 대화가 길어질수록 메모리 보호 기준 아래로 떨어질 수 있었습니다. 무거운 장시간 프롬프트를 동시에 처리하는 동안 메모리 하한에 도달하면 Spark가 멈출 수 있으므로 워치독이 포함되어 있습니다.
기본값 또는 보수적인 CONTEXT 값으로 시작하고, 실제 워크로드로 테스트하며, 긴 대화 기록을 처리하는 동안 여유 메모리를 모니터링하세요. 모델이 성공적으로 로드된 경우에도 캐시된 대화가 커지면 여유 메모리가 줄어들 수 있습니다.
결론
이 저장소는 직접 연결된 두 개의 DGX Spark에 DeepSeek-V4.1-Flash-1017을 자동으로 분산 배포하는 방법을 제공합니다. 하드웨어, RoCE 네트워킹, SSH, Docker, 스토리지 및 Hugging Face 액세스가 준비되면 start.sh가 여러 단계의 설정을 처리하고 익숙한 OpenAI 호환 엔드포인트를 제공합니다.
안정적인 배포를 위해 로컬 Engram 스토리지, 일치하는 GPU 클록, 보수적인 컨텍스트 크기 설정, 이미지·도구·긴 컨텍스트 워크로드에 대한 세심한 검증을 우선하세요. Abliterated 오버레이와 엔진 스위치는 실험에 사용할 수 있지만, 문서화된 성능 및 정확성 측정은 주로 기본 체크포인트와 기본 엔진 구성에 적용됩니다.
