Usar uma imagem personalizada do SO

É possível usar uma imagem personalizada do SO para suas VMs de TPU para pré-carregar software, usar uma distribuição específica do SO ou aplicar modificações personalizadas do kernel. A criação de uma imagem personalizada envolve fazer modificações específicas do sistema durante o processo de criação da imagem e configurar a imagem para processar tarefas de inicialização necessárias para a funcionalidade da TPU.

Lembre-se das seguintes isenções de responsabilidade se você usar uma imagem personalizada do SO com TPUs:

  • O Google oferece imagens padrão do Ubuntu com suporte de longo prazo (LTS) otimizadas para TPU. As mudanças de SO listadas nesta página são validadas apenas para as imagens do Ubuntu LTS otimizadas para TPU com suporte do Google.
  • Você é responsável por extrapolar as mudanças necessárias do SO para qualquer outra distribuição de SO ou imagens personalizadas. O Google não garante que as modificações do Ubuntu listadas nesta página funcionem com outras distribuições de SO ou outra imagem do Ubuntu com um kernel personalizado.
  • O Google não cria nem oferece testes para imagens de SO que não sejam as imagens padrão do Ubuntu LTS otimizadas para TPU. Você precisa criar e testar sua imagem personalizada do SO.

Para mais informações sobre as imagens padrão do Ubuntu LTS otimizadas para TPU, consulte Imagens de SO da TPU.

Pré-requisitos

Sua imagem de base precisa ter os seguintes componentes instalados:

  • Python 3
  • CLI gcloud

Fazer modificações durante a criação da imagem

Aplique as seguintes modificações ao criar sua imagem personalizada do Ubuntu.

Vincular dispositivos de TPU ao VFIO

Para permitir que o SO convidado acesse o hardware da TPU, é necessário vincular dispositivos de TPU ao vfio-pci driver.

  1. Crie um arquivo de regras udev chamado 99-tpu-vfiopci.rules em /etc/udev/rules.d/:

    # Rules for binding vfio-enabled TPU devices to vfio-pci.
    
    # v5p
    SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x0062", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00ad", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci"
    
    # v6e
    SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x006f", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00d1", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci"
    
    # TPU7x
    SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x0076", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00f2", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci"
    
    # Bind all 'bind_to_vfio_pci' tagged devices to vfio-pci.
    TAG=="bind_to_vfio_pci", RUN+="/lib/udev/bind_to_vfio_pci.sh $kernel"
    
  2. Crie um script chamado bind_to_vfio_pci.sh em /lib/udev/:

    #!/bin/bash
    #!/usr/bin/env bash
    
    # Run ./bind_to_vfio_pci.sh <DBDF>
    # Binds the device at <DBDF> to vfio-pci.
    # If the device is already bound to a driver, unbinds it first.
    
    # Load the vfio-pci module into the kernel. No-op if already loaded.
    modprobe vfio-pci
    
    DBDF_REGEX="^[[:xdigit:]]{4}:[[:xdigit:]]{2}:[[:xdigit:]]{2}.[[:xdigit:]]$"
    
    unset BDF
    if [[ $1 =~ $DBDF_REGEX ]]; then
        BDF=$1
    else
        echo "Error: BDF arg ($1) is not in form dddd:bb:dd.f"
        exit 1
    fi
    
    PCI_PATH="/sys/bus/pci/devices/$BDF"
    
    echo "vfio-pci" > "$PCI_PATH/driver_override"
    
    PCI_DRIVER_PATH="$PCI_PATH/driver"
    if [[ -d "$PCI_DRIVER_PATH" ]]; then
        curr_driver=$(readlink "$PCI_DRIVER_PATH")
            curr_driver=${curr_driver##*/}
        if [[ $curr_driver == "vfio-pci" ]]; then
            echo "$BDF already bound to vfio-pci"
            exit 0
        else
            echo "$BDF" > "$PCI_DRIVER_PATH/unbind"
            if [[ -d "$PCI_DRIVER_PATH" ]]; then
                echo "Error: Unable to unbind $PCI_DRIVER_PATH"
                exit 1
            fi
            echo "Unbound $BDF from driver $curr_driver"
        fi
    fi
    echo "$BDF" > /sys/bus/pci/drivers_probe
    echo "Bound $BDF to vfio-pci"
    
    # Grant read/write access on VFIO device to all users
    IOMMU_GROUP=$(readlink "$PCI_PATH/iommu_group" | xargs basename)
    VFIO_DEV="/dev/vfio/$IOMMU_GROUP"
    if [[ -c "$VFIO_DEV" ]]; then
        chmod 0666 "$VFIO_DEV"
    else
        echo "$VFIO_DEV not found"
        exit 1
    fi
    
    # Set allow_unsafe_interrupts for x86 platforms.
    (uname -a | grep -q x86_64) && echo 1 > /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts
    
    # This is only needed to avoid non-zero exit code from previous command.
    echo "All Done!"
    
  3. Torne o script executável:

    chmod +x /lib/udev/bind_to_vfio_pci.sh
    
  4. Conceda acesso ao dispositivo de TPU a todos os usuários do sistema:

    echo 'KERNEL=="accel*" MODE="0666"' >> /etc/udev/rules.d/99-tpu.rules
    

Modificar a imagem para melhorar a performance

Para garantir a performance ideal, ajuste os seguintes limites e parâmetros do sistema.

Limites de memória

Permita que um único processo bloqueie memória ilimitada atualizando /etc/security/limits.conf:

echo '*  hard  memlock  unlimited' >> /etc/security/limits.conf
echo '*  soft  memlock  unlimited' >> /etc/security/limits.conf

Limites de arquivo

Aumente o número de arquivos abertos atualizando /etc/security/limits.conf:

echo "*    soft    nofile       100000" >> /etc/security/limits.conf
echo "*    hard    nofile       100000" >> /etc/security/limits.conf
echo "root soft    nofile       100000" >> /etc/security/limits.conf
echo "root hard    nofile       100000" >> /etc/security/limits.conf

Parâmetros do kernel

Atualize a configuração do GRUB (normalmente em /etc/default/grub) para incluir os seguintes parâmetros em GRUB_CMDLINE_LINUX:

  • idle=poll: impede que a CPU entre em estados de inatividade de baixa energia.
  • intel_iommu=on,sm_on: ativa a unidade de gerenciamento de memória de entrada/saída (IOMMU) da Intel. Necessário para arquiteturas TPU7x e v5p.
  • transparent_hugepage=always: ativa páginas enormes transparentes (THP).

As etapas a seguir mostram como atualizar esses parâmetros do kernel:

  1. Impeça que a CPU entre em um estado de inatividade de baixa energia definindo a seguinte variável, que será usada na próxima etapa.

    kernel_cmdline="idle=poll"
    
  2. Ative a unidade de gerenciamento de memória de entrada/saída (IOMMU) da Intel. Essa etapa é necessária para TPU7x e TPU v5p.

    kernel_cmdline="${kernel_cmdline} intel_iommu=on,sm_on";
    sed -i "s/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"${kernel_cmdline}\"/" /etc/default/grub
    echo "Status: New kernel cmdline: $(cat /etc/default/grub | grep -e '^GRUB_CMDLINE_LINUX=')"
    
    update-grub
    
  3. Ative páginas enormes transparentes (THP):