MLX-Gewichtsshards auf dem Cloud-Mac prüfen

MLX-Gewichtsshards auf dem Cloud-Mac prüfen

MLX-Gewichtsshards auf dem Cloud-Mac prüfen

Wenn sich ein Modell nach der Übertragung seiner Gewichte auf einen Cloud-Mac nicht laden lässt, liegt das nicht zwangsläufig an zu wenig gemeinsamem Arbeitsspeicher. Ein abgebrochener Download, Shards aus unterschiedlichen Modellversionen oder ein Index, der auf alte Dateien verweist, können ein Experiment schon beim ersten Schritt stoppen. Wer vor dem Start von MLX zunächst die Dateien prüft, ohne Tensoren zu laden, vermeidet unnötige erneute Downloads und das blinde Anpassen von Inferenzparametern.

Zuerst ein festes Gewichtsverzeichnis anlegen

Legen Sie bei der Prüfung auf OsxNode die Gewichte, die Konfiguration und den Index eines Experiments in einem eigenen Verzeichnis weights ab. Überschreiben Sie dabei kein Modell, das gerade ausgeführt wird. Benötigt wird Python 3; speichern Sie das Prüfskript außerhalb des Gewichtsverzeichnisses. Dieser Artikel behandelt ausschließlich safetensors-Gewichte und führt keinen mit dem Modell gelieferten Code aus.

Dokumentieren Sie die Modellrevision, die Quantisierungskonfiguration, die Downloadquelle und die Dateiliste. Diese Angaben müssen der tatsächlich bezogenen Version entsprechen; ein Modellname allein, dessen Zuordnung sich ändern kann, reicht nicht aus. Beginnen Sie die Prüfung erst, nachdem der Downloadprozess beendet ist, damit noch nicht fertig geschriebene Shards nicht fälschlich als beschädigt gelten.

Eine gültige Dateistruktur, eine unveränderte Übertragung und erfolgreiche Modellinferenz sind drei unterschiedliche Prüfergebnisse. Keines davon bestätigt automatisch die beiden anderen.

Offsets und Index anhand der Dateiheader prüfen

Die ersten acht Bytes einer safetensors-Datei enthalten eine vorzeichenlose Ganzzahl in Little-Endian-Reihenfolge, die die Länge des JSON-Headers in Bytes angibt. Die data_offsets der Tensoren beziehen sich auf den Datenbereich nach dem Header, nicht auf den Dateianfang. Wer diese beiden Bezugspunkte verwechselt, meldet bei intakten Shards fälschlich eine Bereichsüberschreitung.

Das folgende Skript prüft, ob der Datenbereich lückenlos abgedeckt ist, ob Tensornamen in mehreren Shards vorkommen und ob die Indexzuordnung mit den tatsächlichen Dateien übereinstimmt. Speichern Sie es als verify_weights.py. Die Headergrenze von 16MiB ist eine lokale Prüfregel und keine Grenze des Dateiformats. Bei einem gültigen größeren Header sollten Sie zunächst die Herkunft prüfen und erst dann den Grenzwert anpassen.

import json
import struct
import sys
from pathlib import Path

def require(ok, message):
    if not ok:
        raise ValueError(message)

def unique_object(pairs):
    result = {}
    for key, value in pairs:
        require(key not in result, f"Duplicate JSON key: {key}")
        result[key] = value
    return result

def read_json(raw):
    return json.loads(raw, object_pairs_hook=unique_object)

def verify(root):
    require(root.is_dir(), "Missing model directory")
    files = sorted(root.glob("*.safetensors"))
    require(bool(files), "No safetensors files")
    actual = {}

    for path in files:
        require(not path.is_symlink(), "Symlink shard rejected")
        size = path.stat().st_size
        with path.open("rb") as stream:
            raw = stream.read(8)
            require(len(raw) == 8, f"Short prefix: {path.name}")
            length = struct.unpack("<Q", raw)[0]
            require(
                0 < length <= min(16 * 1024 * 1024, size - 8),
                f"Invalid header length: {path.name}"
            )
            header = read_json(stream.read(length))

        require(isinstance(header, dict), "Header must be an object")
        data_size = size - 8 - length
        ranges = []
        for name, info in header.items():
            if name == "__metadata__":
                continue
            require(isinstance(info, dict), f"Invalid tensor: {name}")
            offsets = info.get("data_offsets")
            require(
                isinstance(offsets, list) and len(offsets) == 2
                and all(type(v) is int for v in offsets),
                f"Invalid offsets: {name}"
            )
            start, end = offsets
            require(0 <= start <= end <= data_size,
                    f"Out of bounds: {name}")
            require(name not in actual, f"Duplicate tensor: {name}")
            actual[name] = path.name
            ranges.append((start, end))

        cursor = 0
        for start, end in sorted(ranges):
            require(start == cursor, f"Gap or overlap: {path.name}")
            cursor = end
        require(cursor == data_size, f"Trailing data: {path.name}")

    index = root / "model.safetensors.index.json"
    if index.exists():
        document = read_json(index.read_text(encoding="utf-8"))
        mapping = document.get("weight_map")
        require(isinstance(mapping, dict), "Missing weight_map")
        require(mapping == actual, "Shard index mismatch")
    else:
        require(len(files) == 1, "Multiple shards require an index")

    print(f"PASS: {len(files)} files, {len(actual)} tensors")

try:
    require(len(sys.argv) == 2, "Usage: verify_weights.py DIRECTORY")
    verify(Path(sys.argv[1]))
except Exception as error:
    print(f"FAIL: {error}", file=sys.stderr)
    sys.exit(1)

Führen Sie python3 verify_weights.py weights aus und fahren Sie nur bei Exitcode null fort. Das Skript setzt den Standarddateinamen für den Index voraus und erwartet die Shards direkt im Gewichtsverzeichnis. Andere Verzeichnisstrukturen müssen ausdrücklich berücksichtigt werden; löschen Sie nicht einfach den Index, um die Prüfung zu umgehen.

Die Übertragung mit Hashwerten der Quelle prüfen

Die Strukturprüfung erkennt keine beschädigten Zahlenwerte innerhalb der Tensoren. Erstellen Sie deshalb auf der vertrauenswürdigen Quellmaschine eine Prüfsummenliste, nachdem alle Dateien vollständig geschrieben wurden. Übertragen Sie anschließend genau diese Dateien zusammen mit der Liste auf die Zielmaschine. Alle folgenden Befehle werden im Gewichtsverzeichnis ausgeführt:

shasum -a 256 ./*.safetensors ./config.json > SHA256SUMS

Falls ein Shard-Index vorhanden ist, nehmen Sie ihn ebenfalls in die Liste auf:

shasum -a 256 ./model.safetensors.index.json >> SHA256SUMS

Wechseln Sie auf der Zielmaschine in das entsprechende Verzeichnis und führen Sie Folgendes aus:

shasum -a 256 -c SHA256SUMS

Für jede aufgeführte Datei muss OK erscheinen. Die Prüfsummenliste selbst muss über einen vertrauenswürdigen Kanal bezogen werden. Kann ein Angreifer sowohl die Dateien als auch die Liste ersetzen, liefern die Hashwerte keinen Herkunftsnachweis. Auch Gewichte, die bereits an der Quelle beschädigt waren, bestehen den Übertragungsabgleich unverändert. Die Strukturprüfung bleibt daher erforderlich.

Fehler gezielt beheben statt alles erneut herunterzuladen

Bei Short prefix oder einer ungültigen Headerlänge prüfen Sie zuerst, ob der Downloadprozess beendet ist, und kontrollieren anschließend die Byteanzahl des betroffenen Shards. Füllen Sie Dateien nicht von Hand auf und benennen Sie keine beim Download erhaltene Fehlerseite in eine Gewichtsdatei um.

Bei Shard index mismatch vergleichen Sie die Dateinamen im Index einzeln mit dem Verzeichnisinhalt. Häufig fehlen nach dem Kopieren einzelne Shards, oder Dateien einer alten Version sind zurückgeblieben. Verschieben Sie überzählige Dateien zunächst in ein separates Verzeichnis und wiederholen Sie die Prüfung. Ändern Sie nicht den Index, nur damit er zu einem Satz von Gewichten unbekannter Herkunft passt.

Wenn die Strukturprüfung erfolgreich ist, aber der Hashabgleich fehlschlägt, beschaffen Sie nur die betroffenen Dateien erneut und wiederholen danach sämtliche Prüfungen. Unterstützt das Übertragungswerkzeug die Wiederaufnahme abgebrochener Transfers, vergewissern Sie sich zuerst, dass die Quelldatei auf der entfernten Maschine nicht durch eine andere Version ersetzt wurde. Andernfalls können die erste Hälfte der alten Datei und die zweite Hälfte der neuen Datei zusammengesetzt werden.

Erst wenn die Hashprüfung erfolgreich ist, das Laden aber weiterhin scheitert, untersuchen Sie die Modellarchitektur, die Quantisierungskonfiguration, die Versionen der Laufzeitbibliotheken und den Speicherdruck. Diese Reihenfolge trennt Dateifehler von Problemen der Laufzeitumgebung, ohne die Ursache aus Fehlermeldungen erraten zu müssen.

Die Prüfungen vor jedem Experiment ausführen

Das Skript prüft weder den mathematischen Zusammenhang zwischen dtype, shape und der Byteanzahl eines Tensors noch die Kompatibilität der Quantisierungsparameter. Abschließend müssen Sie das Modell daher weiterhin in einer MLX-Umgebung mit festgelegten Versionen laden und mit einer festen Eingabe eine kurze Ausgabe erzeugen. Eine reine Headerprüfung ersetzt diesen Schritt nicht.

Bewahren Sie in den Experimentaufzeichnungen mindestens die Modellrevision, die Prüfsummenliste, den Exitcode des Skripts, die Versionen der Laufzeitbibliotheken und das Ergebnis des ersten Ladeversuchs auf. Ein Screenshot eines erfolgreichen Durchlaufs allein reicht nicht: Sobald sich der Verzeichnisinhalt ändert, lassen sich Unterschiede damit kaum noch erklären.

Schalten Sie Strukturprüfung und Hashabgleich dem eigentlichen Experiment im Skript vor und brechen Sie alle weiteren Aufgaben ab, sobald eine Prüfung fehlschlägt. Verwenden Sie beim Wechsel der Modellrevision ein neues Verzeichnis und erstellen Sie eine neue Referenzbasis. Sichern Sie die Prüfsummenliste und die Prüfprotokolle vor Ende der Mietzeit. So übernimmt die nächste Maschine nachvollziehbar geprüfte Eingabedaten für das Experiment – und nicht bloß einen Ordner mit dem Etikett „Download abgeschlossen“.

Häufig gestellte Fragen

Garantiert eine bestandene Strukturprüfung korrekte Inferenz?

Nein. Sie prüft Dateiaufbau und Index, nicht Tensorwerte oder Modellkonfiguration. Danach müssen das Modell in einer passenden Umgebung geladen und feste Eingaben getestet werden.

Reicht eine erst nach dem Transfer erzeugte SHA-256-Liste?

Sie erkennt spätere Änderungen, belegt aber nicht die Richtigkeit dieses Transfers. Erzeugen Sie die Liste an einer vertrauenswürdigen Quelle und beziehen Sie sie über einen vertrauenswürdigen Kanal.

Mac passend zur Versuchsdauer mieten

Exklusiver Mac mini M4 mit 16 GB gemeinsamem Arbeitsspeicher und 256 GB SSD. Vorauszahlung für Tage, Wochen, Monate oder Quartale; ohne Verlängerung wird das Gerät nach Ablauf gestoppt. Modelle und Laufzeitumgebung richten Sie selbst ein. Maßgeblich ist der Echtzeitstatus in der Konsole.

Mac tageweise mieten

Erst Konfiguration prüfen, dann loslegen

Prüfen Sie Modellgewichte, Spitzenauslastung und Mietdauer, bevor Sie einen Zeitraum auswählen. Eine Anleitung zur Verbindung finden Sie im Hilfe-Center.