Arbeite die Speicherverbraucher der Reihe nach ab: Batch Size und Sequenzlänge, für den Backward Pass gehaltene Aktivierungen, Optimizer State und Fragmentierung durch variable Shapes. Schnelle Gegenmittel sind ein kleinerer Batch mit Gradient Accumulation, um die effektive Batch Size zu erhalten, Gradient Checkpointing, bf16 und ein speichereffizienter Optimizer. Prüf außerdem, dass du keine Tensoren sammelst, die noch einen Computation Graph mitschleppen.
Warum Interviewer das fragen
Das ist tägliche Realität für alle, die Modelle trainieren, der Interviewer prüft also auf eine systematische Methode statt auf zufälliges Flag-Umlegen. Das Detail, das Erfahrung verrät, ist zu wissen, dass meist die Aktivierungen und nicht die Gewichte dominieren, dazu der klassische Bug, jeden Step einen Loss-Tensor an eine Liste zu hängen, der den ganzen Graphen hält und Speicher über Iterationen hinweg leckt.
So baust du deine Antwort auf
- Listen die Speicherverbraucher grob nach Größe auf.
- Unterscheide ein Kapazitätsproblem von einem Leck, das über die Steps wächst.
- Gib die billigen Gegenmittel: Accumulation, Checkpointing, bf16.
- Nenn den Bug mit dem gehaltenen Graphen und wie du ihn erkennst.
Beispielantwort
Als Erstes prüfe ich, ob es sofort stirbt oder nach ein paar hundert Steps, weil das verschiedene Bugs sind. Sofort ist ein Kapazitätsproblem, wachsend ist ein Leck. Bei Kapazität schlüssele ich auf, was tatsächlich resident ist: Gewichte, Gradienten, Optimizer State (bei Adam sind das zwei zusätzliche Kopien) und für den Backward gespeicherte Aktivierungen. Bei einem Transformer dominieren üblicherweise die Aktivierungen, und die skalieren mit Batch Size mal Sequenzlänge, das sind also die ersten Regler. Ich senke den Batch und nutze Gradient Accumulation, um die effektive Batch Size identisch zu halten, das kostet Wall Clock und sonst nichts. Danach Gradient Checkpointing, das Aktivierungen im Backward neu berechnet und grob dreißig Prozent zusätzliche Rechenzeit gegen eine große Speicherersparnis tauscht. bf16 halbiert obendrauf die Aktivierungsgröße. Wenn es über die Steps wächst, hält etwas einen Graphen. Der Klassiker ist, den rohen Loss-Tensor fürs Logging an eine Liste zu hängen, was den Computation Graph jedes Steps am Leben hält, und die Lösung ist ein Aufruf von item darauf. Ich bestätige das, indem ich alle hundert Steps allocated und reserved memory ausgebe, denn eine saubere Treppe nach oben ist das Verräterische.
Steht dieses Vorstellungsgespräch bald an? GhostPilot hört bei deinem Live-Call mit, erkennt die Frage in dem Moment, in dem sie gestellt wird, und bringt dir eine strukturierte Antwort in Echtzeit auf den Bildschirm. Probier es im nächsten Mock aus, oder hol dir einen $29 Session Pass, kein Abo, für den Ernstfall.
So funktioniert esNachfragen, mit denen du rechnen solltest
- Was ist der Unterschied zwischen allocated und reserved memory im Allocator?
- Wie entsteht Speicherfragmentierung bei Inputs variabler Länge?
- Wann würdest du CPU Offloading nutzen statt den Batch zu verkleinern?
Weitere Fragen für Machine Learning Engineer
Dein Interviewer stellt seine eigene Version davon. Kopier deine echte Stellenbeschreibung in den kostenlosen Question Predictor und bekomm die 20 Fragen, die diese Rolle am wahrscheinlichsten stellt, samt dem, worauf jede wirklich abzielt.
Meine Fragen vorhersagen