Planuj obciążenia GPU i twórz zadania kompozycji

Użyj Declarative Automation Bundles do zaplanowania obciążenia AI Runtime GPU i połączenia go z innymi zadaniami, takimi jak wstępne przygotowanie danych. Zdefiniuj obciążenie i jego harmonogram w YAML, a następnie wdroż je jako zadanie. Dla potoku treningowego uruchom wstępne przetwarzanie na zasobach CPU i rozpocznij trening GPU po przygotowaniu danych.

Ten przewodnik zaczyna się od zadania, które drukuje "Hello world", a następnie buduje zaplanowany potok wstępnego przetwarzania i szkolenia. Jeśli masz już obciążenie AI Runtime YAML, zobacz Przekształć obciążenie AI Runtime w pakiet.

Jak to działa

  • bundle zawiera Twój kod i databricks.yml konfigurację.
  • Operacja wsadowa grupuje zadania i definiuje, kiedy się uruchamiają.
  • ai_runtime_task uruchamia twoje polecenie na AI Runtime.

Pole depends_on łączy zadania w skierowany graf acykliczny (DAG), a pole schedule harmonogramuje uruchamianie zadania cyklicznie.

databricks bundle deploy przesyła kod i tworzy lub aktualizuje zadanie. databricks bundle run Natychmiast rozpoczyna się uruchomienie zlecenia. Przy każdym uruchomieniu AI Runtime przydziela zasoby obliczeniowe GPU, wykonuje twoje polecenie i rejestruje ten przebieg w nazwanym eksperymencie MLflow.

Requirements

Hello world przykład z ai_runtime_task

Ten przykład uruchamia polecenie powłoki na jednym GPU A10.

  1. Stwórz katalog dla pakietu. W tym katalogu stwórz command.sh z następującą zawartością:

    #!/usr/bin/env bash
    set -euo pipefail
    echo "Hello world"
    
  2. Utwórz databricks.yml w tym samym katalogu:

    bundle:
      name: hello-ai-runtime
    
    resources:
      jobs:
        hello:
          name: hello-ai-runtime
          tasks:
            - task_key: hello
              environment_key: default
              ai_runtime_task:
                experiment: hello-ai-runtime
                deployments:
                  - command_path: ${workspace.file_path}/command.sh
                    compute:
                      accelerator_type: GPU_1xA10
                      accelerator_count: 1
          environments:
            - environment_key: default
              spec:
                environment_version: '6'
    
    targets:
      dev:
        mode: development
        default: true
    
  3. Z katalogu pakietów zweryfikuj, wdroż i wykonaj zadanie:

    databricks bundle validate --target dev
    databricks bundle deploy --target dev
    databricks bundle run hello --target dev
    
  4. Otwórz URL run wydrukowany przez CLI i zobacz wyjście zadania hello . Zawiera Hello world. Run pojawia się także w hello-ai-runtime eksperymencie MLflow.

Bardziej złożony przykład: Zaplanuj potok wstępnego przetwarzania i trenowania

Ten przykład przygotowuje mały zbiór danych z wykorzystaniem mocy obliczeniowej CPU, a następnie trenuje model liniowy na jednym GPU A10. Oba zadania używają tego samego pliku woluminu do przekazywania danych między sobą. Zadanie jest zaplanowane codziennie na 09:00 UTC, z zawieszonym harmonogramem, dopóki go nie przetestujesz.

Tworzenie projektu

  1. Stwórz osobny katalog o następującym układzie:

    scheduled-training/
    ├── databricks.yml
    ├── prep.py
    ├── command.sh
    └── src/
        └── train.py
    
  2. Utwórz prep.py z następującą zawartością. Zastąp <catalog>, <schema> i <volume> nazwami swoich woluminów. Ten notebook źródłowy normalizuje wartości wejściowe i zapisuje przygotowane dane do wolumenu:

    # Databricks notebook source
    import json
    from pathlib import Path
    
    data_path = Path("/Volumes/<catalog>/<schema>/<volume>/scheduled-training/data.json")
    inputs = [value / 10 for value in range(10)]
    data = {"x": inputs, "y": [2 * value + 1 for value in inputs]}
    data_path.parent.mkdir(parents=True, exist_ok=True)
    data_path.write_text(json.dumps(data))
    print(f"Prepared {len(inputs)} rows at {data_path}")
    
  3. Utwórz src/train.py z następującą zawartością. Użyj tej samej ścieżki woluminu co w prep.py:

    import json
    from pathlib import Path
    
    import torch
    
    data_path = Path("/Volumes/<catalog>/<schema>/<volume>/scheduled-training/data.json")
    data = json.loads(data_path.read_text())
    x = torch.tensor(data["x"], device="cuda").reshape(-1, 1)
    y = torch.tensor(data["y"], device="cuda").reshape(-1, 1)
    model = torch.nn.Linear(1, 1).to("cuda")
    optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
    
    for _ in range(200):
        optimizer.zero_grad()
        loss = torch.nn.functional.mse_loss(model(x), y)
        loss.backward()
        optimizer.step()
    
    print(f"Trained on {x.device}: loss={loss.item():.4f}")
    
  4. Utwórz command.sh, aby uruchomić kod treningowy. Pakiet poniżej zawiera src/, więc CODE_SOURCE_PATH wskazuje na wyodrębniony katalog src:

    #!/usr/bin/env bash
    set -euo pipefail
    cd "$CODE_SOURCE_PATH"
    python train.py
    
  5. Utwórz databricks.yml z następującą zawartością. Pakiet zawiera src/ do zadania GPU. Notebook prep działa na bezserwerowych zasobach CPU, a depends_on uruchamia train dopiero gdy prep zakończy się powodzeniem. max_concurrent_runs: 1 zapobiega wzajemnemu nadpisywaniu pliku wejściowego przez uruchomienia tego zadania:

    bundle:
      name: scheduled-training
    
    artifacts:
      code:
        type: tgz
        path: .
        include: [src]
        files:
          - source: ./dist/code.tgz
    
    resources:
      jobs:
        train_pipeline:
          name: scheduled-training
          max_concurrent_runs: 1
          schedule:
            quartz_cron_expression: '0 0 9 * * ?'
            timezone_id: UTC
            pause_status: PAUSED
          tasks:
            - task_key: prep
              notebook_task:
                notebook_path: ./prep.py
            - task_key: train
              depends_on:
                - task_key: prep
              environment_key: training
              ai_runtime_task:
                experiment: scheduled-training
                code_source_path: ./dist/code.tgz
                deployments:
                  - command_path: ${workspace.file_path}/command.sh
                    compute:
                      accelerator_type: GPU_1xA10
                      accelerator_count: 1
          environments:
            - environment_key: training
              spec:
                environment_version: '6'
                dependencies:
                  - torch
    
    targets:
      dev:
        mode: development
        default: true
    

Przetestuj i włącz harmonogram

  1. Z scheduled-training/, wdroż pakiet i rozpocznij uruchomienie ręczne:

    databricks bundle validate --target dev
    databricks bundle deploy --target dev
    databricks bundle run train_pipeline --target dev
    
  2. Otwórz adres URL uruchomienia wyświetlony przez CLI. Upewnij się, że prep zakończy się powodzeniem, zanim train się rozpocznie. Dane wyjściowe prep raportują 10 przygotowanych wierszy, a dane wyjściowe train raportują Trained on cuda:0 oraz stratę.

  3. W databricks.yml zmień w harmonogramie wartość pause_status z PAUSED na UNPAUSED. Blok harmonogramu jest już następujący:

    schedule:
      quartz_cron_expression: '0 0 9 * * ?'
      timezone_id: UTC
      pause_status: UNPAUSED
    
  4. Wdroż zmianę, aby aktywować dzienny harmonogram:

    databricks bundle deploy --target dev
    

    Ustawienie pause_status: UNPAUSED wyraźnie umożliwia ten harmonogram nawet dla celu rozwojowego. W Jobs & Pipelines otwórz wdrożone zadanie i potwierdź, że jego harmonogram jest aktywny na 09:00 UTC. Zobacz Uruchamianie zadań zgodnie z harmonogramem.

Aby wstrzymać zaplanowane uruchomienia, ustaw pause_status: PAUSED i wdroż ponownie. Aby usunąć przykładowe zadanie oraz pliki przesłane przez bundle, uruchom następujące z katalogu bundle:

databricks bundle destroy --target dev

Przygotowane dane na woluminie pozostaną. Usuń scheduled-training katalog danych, gdy już go nie potrzebujesz.

Dodatkowe zasoby