Executar um pipeline com GPUs

Nesta página, explicamos como executar um pipeline do Apache Beam no Dataflow com GPUs. Os jobs que usam GPUs geram cobranças, conforme especificado na página de preços do Dataflow.

Para mais informações sobre o uso de GPUs com o Dataflow, acesse Suporte do Dataflow para GPUs. Para mais informações sobre o fluxo de trabalho do desenvolvedor para criar pipelines usando GPUs, consulte Sobre GPUs com o Dataflow.

Usar notebooks do Apache Beam

Se você já tiver um pipeline que queira executar com GPUs no Dataflow, pule esta seção.

Os notebooks do Apache Beam oferecem uma maneira conveniente de prototipar e desenvolver iterativamente o pipeline com GPUs sem configurar um ambiente de desenvolvimento. Para começar, leia o guia Como desenvolver com os notebooks do Apache Beam, inicie uma instância de notebooks do Apache Beam e siga o exemplo Usar GPUs com Apache Beam.

Provisionar cota de GPU

Os dispositivos da GPU estão sujeitos à disponibilidade de cota do seu projeto do Google Cloud. Solicite a cota de GPU na região de sua escolha.

Instalar os drivers da GPU

Para instalar drivers NVIDIA nos workers do Dataflow, anexe install-nvidia-driver à opção de serviço worker_accelerator.

Quando você especifica a opção install-nvidia-driver, o Dataflow instala drivers NVIDIA nos workers do Dataflow usando o utilitário cos-extensions fornecido pelo Container-Optimized OS. Ao especificar install-nvidia-driver, os usuários concordam com o contrato de licença da NVIDIA.

Binários e bibliotecas fornecidos pelo instalador de driver da NVIDIA são instalados no contêiner que executa o código do usuário do pipeline em /usr/local/nvidia/.

A versão do driver da GPU depende da versão do Container-Optimized OS usada pelo Dataflow. Para encontrar a versão do driver da GPU de um job do Dataflow, nos registros da etapa do Dataflow do job, pesquise GPU driver.

Criar uma imagem de contêiner personalizada

Para interagir com as GPUs, talvez seja necessário usar software NVIDIA adicional, como bibliotecas aceleradas por GPU e o Kit de ferramentas do CUDA. Forneça essas bibliotecas no contêiner do Docker com o código do usuário em execução.

Para personalizar a imagem do contêiner, forneça uma imagem que cumpra o contrato da imagem de contêiner do SDK do Apache Beam e tenha as bibliotecas de GPU necessárias.

Para fornecer uma imagem de contêiner personalizada, é necessário usar o Dataflow Runner v2 e fornecer a imagem do contêiner usando a opção sdk_container_image do pipeline. Se você estiver usando o Apache Beam versão 2.29.0 ou anterior, use a opção de pipeline worker_harness_container_image. Para mais informações, consulte Usar contêineres personalizados.

Para criar uma imagem de contêiner personalizada, use uma das duas abordagens a seguir:

Usar uma imagem existente configurada para uso da GPU

É possível criar uma imagem do Docker que atenda ao contrato de contêiner do SDK do Apache Beam a partir de uma imagem de base pré-configurada para uso da GPU. Por exemplo, as imagens Docker do TensorFlow e as imagens de contêiner da NVIDIA são pré-configuradas para uso da GPU.

Um exemplo de Dockerfile baseado na imagem Docker do TensorFlow com o Python 3.6 é semelhante a este:

ARG BASE=tensorflow/tensorflow:2.5.0-gpu
FROM $BASE

# Check that the chosen base image provides the expected version of Python interpreter.
ARG PY_VERSION=3.6
RUN [[ $PY_VERSION == `python -c 'import sys; print("%s.%s" % sys.version_info[0:2])'` ]] \
   || { echo "Could not find Python interpreter or Python version is different from ${PY_VERSION}"; exit 1; }

RUN pip install --upgrade pip \
    && pip install --no-cache-dir apache-beam[gcp]==2.29.0 \
    # Verify that there are no conflicting dependencies.
    && pip check

# Copy the Apache Beam worker dependencies from the Beam Python 3.6 SDK image.
COPY --from=apache/beam_python3.6_sdk:2.29.0 /opt/apache/beam /opt/apache/beam

# Apache Beam worker expects pip at /usr/local/bin/pip by default.
# Some images have pip in a different location. If necessary, make a symlink.
# This line can be omitted in Beam 2.30.0 and later versions.
RUN [[ `which pip` == "/usr/local/bin/pip" ]] || ln -s `which pip` /usr/local/bin/pip

# Set the entrypoint to Apache Beam SDK worker launcher.
ENTRYPOINT [ "/opt/apache/beam/boot" ]

Ao usar imagens Docker do TensorFlow, use o TensorFlow 2.5.0 ou posterior. Imagens anteriores do Docker do TensorFlow instalam o pacote tensorflow-gpu em vez do pacote tensorflow. A distinção não é importante após o lançamento do TensorFlow 2.1.0, mas vários pacotes downstream, como tfx, exigem o pacote tensorflow.

Os contêineres grandes atrasam a inicialização do worker. Essa mudança de desempenho pode ocorrer ao usar contêineres como o Deep Learning Containers.

Instalar uma versão específica do Python

Se você tiver requisitos rígidos para a versão do Python, crie sua imagem baseada em uma imagem da NVIDIA que tenha as bibliotecas de GPU necessárias. Em seguida, instale o interpretador do Python.

Veja no exemplo a seguir como selecionar uma imagem da NVIDIA que não contém o interpretador do Python no catálogo de imagens de contêiner do CUDA. Ajuste o exemplo para instalar a versão necessária do Python 3 e pip. O exemplo usa o TensorFlow. Portanto, ao escolher uma imagem, as versões CUDA e cuDNN na imagem base atendem aos requisitos da versão do TensorFlow.

Uma amostra do Dockerfile se parece com o seguinte:

# Select an NVIDIA base image with needed GPU stack from https://ngc.nvidia.com/catalog/containers/nvidia:cuda

FROM nvidia/cuda:11.0.3-cudnn8-runtime-ubuntu20.04

RUN \
    # Add Deadsnakes repository that has a variety of Python packages for Ubuntu.
    # See: https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa
    apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F23C5A6CF475977595C89F51BA6932366A755776 \
    && echo "deb http://ppa.launchpad.net/deadsnakes/ppa/ubuntu focal main" >> /etc/apt/sources.list.d/custom.list \
    && echo "deb-src http://ppa.launchpad.net/deadsnakes/ppa/ubuntu focal main" >> /etc/apt/sources.list.d/custom.list \
    && apt-get update \
    && apt-get install -y curl \
        python3.8 \
        # With python3.8 package, distutils need to be installed separately.
        python3-distutils \
    && rm -rf /var/lib/apt/lists/* \
    && update-alternatives --install /usr/bin/python python /usr/bin/python3.8 10 \
    && curl https://bootstrap.pypa.io/get-pip.py | python \
    && pip install --upgrade pip \
    # Install Apache Beam and Python packages that will interact with GPUs.
    && pip install --no-cache-dir apache-beam[gcp]==2.29.0 tensorflow==2.4.0 \
    # Verify that there are no conflicting dependencies.
    && pip check

# Copy the Apache Beam worker dependencies from the Beam Python 3.8 SDK image.
COPY --from=apache/beam_python3.8_sdk:2.29.0 /opt/apache/beam /opt/apache/beam

# Set the entrypoint to Apache Beam SDK worker launcher.
ENTRYPOINT [ "/opt/apache/beam/boot" ]

Em algumas distribuições do SO, pode ser difícil instalar versões específicas do Python usando o gerenciador de pacotes do SO. Nesse caso, instale o interpretador do Python com ferramentas como o Miniconda ou o pyenv.

Uma amostra do Dockerfile se parece com o seguinte:

FROM nvidia/cuda:11.0.3-cudnn8-runtime-ubuntu20.04

# The Python version of the Dockerfile must match the Python version you use
# to launch the Dataflow job.

ARG PYTHON_VERSION=3.8

# Update PATH so we find our new Conda and Python installations.
ENV PATH=/opt/python/bin:/opt/conda/bin:$PATH

RUN apt-get update \
    && apt-get install -y wget \
    && rm -rf /var/lib/apt/lists/* \
    # The NVIDIA image doesn't come with Python pre-installed.
    # We use Miniconda to install the Python version of our choice.
    && wget -q https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \
    && bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/conda \
    && rm Miniconda3-latest-Linux-x86_64.sh \
    # Create a new Python environment with needed version, and install pip.
    && conda create -y -p /opt/python python=$PYTHON_VERSION pip \
    # Remove unused Conda packages, install necessary Python packages via pip
    # to avoid mixing packages from pip and Conda.
    && conda clean -y --all --force-pkgs-dirs \
    && pip install --upgrade pip \
    # Install Apache Beam and Python packages that will interact with GPUs.
    && pip install --no-cache-dir apache-beam[gcp]==2.29.0 tensorflow==2.4.0 \
    # Verify that there are no conflicting dependencies.
    && pip check \
    # Apache Beam worker expects pip at /usr/local/bin/pip by default.
    # You can omit this line when using Beam 2.30.0 and later versions.
    && ln -s $(which pip) /usr/local/bin/pip

# Copy the Apache Beam worker dependencies from the Apache Beam SDK for Python 3.8 image.
COPY --from=apache/beam_python3.8_sdk:2.29.0 /opt/apache/beam /opt/apache/beam

# Set the entrypoint to Apache Beam SDK worker launcher.
ENTRYPOINT [ "/opt/apache/beam/boot" ]

Usar uma imagem de contêiner do Apache Beam

É possível configurar uma imagem de contêiner para uso da GPU sem usar imagens pré-configuradas. Essa abordagem é recomendada apenas quando imagens pré-configuradas não funcionam para você. Para configurar sua própria imagem de contêiner, você precisa selecionar bibliotecas compatíveis e configurar o ambiente de execução.

Uma amostra do Dockerfile se parece com o seguinte:

FROM apache/beam_python3.7_sdk:2.24.0
ENV INSTALLER_DIR="/tmp/installer_dir"

# The base image has TensorFlow 2.2.0, which requires CUDA 10.1 and cuDNN 7.6.
# You can download cuDNN from NVIDIA website
# https://developer.nvidia.com/cudnn
COPY cudnn-10.1-linux-x64-v7.6.0.64.tgz $INSTALLER_DIR/cudnn.tgz
RUN \
    # Download CUDA toolkit.
    wget -q -O $INSTALLER_DIR/cuda.run https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.243_418.87.00_linux.run && \

    # Install CUDA toolkit. Print logs upon failure.
    sh $INSTALLER_DIR/cuda.run --toolkit --silent || (egrep '^\[ERROR\]' /var/log/cuda-installer.log && exit 1) && \
    # Install cuDNN.
    mkdir $INSTALLER_DIR/cudnn && \
    tar xvfz $INSTALLER_DIR/cudnn.tgz -C $INSTALLER_DIR/cudnn && \

    cp $INSTALLER_DIR/cudnn/cuda/include/cudnn*.h /usr/local/cuda/include && \
    cp $INSTALLER_DIR/cudnn/cuda/lib64/libcudnn* /usr/local/cuda/lib64 && \
    chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn* && \
    rm -rf $INSTALLER_DIR

# A volume with GPU drivers will be mounted at runtime at /usr/local/nvidia.
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/nvidia/lib64:/usr/local/cuda/lib64

As bibliotecas de drivers em /usr/local/nvidia/lib64 precisam ser detectáveis no contêiner como bibliotecas compartilhadas. Para tornar as bibliotecas de driver detectáveis, configure a variável de ambiente LD_LIBRARY_PATH.

Para usar o TensorFlow, é preciso escolher uma combinação compatível de versões do CUDA Toolkit e do cuDNN. Para mais informações, leia Requisitos de software e Configurações do build testadas.

Selecionar o tipo e o número de GPUs para workers do Dataflow

Para configurar o tipo e o número de GPUs a serem anexados aos workers do Dataflow, use a opção de serviço worker_accelerator. Selecione o tipo e o número de GPUs com base no seu caso de uso e como você planeja utilizar as GPUs no pipeline.

Para uma lista de tipos de GPU compatíveis com o Dataflow, consulte Suporte do Dataflow para GPUs.

Executar o job com GPUs

As considerações para executar um job do Dataflow com GPUs incluem:

  • Como os contêineres de GPU geralmente são grandes, para evitar a falta de espaço em disco, faça isto:

  • Considere a quantidade de processos que usam simultaneamente a mesma GPU em uma VM de worker. Em seguida, decida se quer limitar a GPU a um único processo ou permitir que vários processos usem a GPU.

    • Se um processo do SDK do Apache Beam puder usar a maior parte da memória disponível da GPU, por exemplo, carregando um modelo grande em uma GPU, configure os workers para usarem um único processo definindo a opção de pipeline --experiments=no_use_multiple_sdk_containers. Outra possibilidade é usar os workers com uma vCPU usando um tipo de máquina personalizado, como n1-custom-1-NUMBER_OF_MB ou n1-custom-1-NUMBER_OF_MB-ext, para extensão de memória. Para mais informações, consulte Usar um tipo de máquina com mais memória por vCPU.
    • Se a GPU for compartilhada por vários processos, ative o processamento simultâneo em uma GPU compartilhada usando o NVIDIA Multi-Processing Service (MPS).

    Para mais informações, consulte GPUs e paralelismo de worker.

Para executar um job do Dataflow com GPUs, use o seguinte comando: Para usar o ajuste direito, em vez de usar a opção de serviço worker_accelerator, use a dica de recurso accelerator.

Python

python PIPELINE \
  --runner "DataflowRunner" \
  --project "PROJECT" \
  --temp_location "gs://BUCKET/tmp" \
  --region "REGION" \
  --worker_harness_container_image "IMAGE" \
  --disk_size_gb "DISK_SIZE_GB" \
  --dataflow_service_options "worker_accelerator=type:GPU_TYPE;count:GPU_COUNT;install-nvidia-driver" \
  --experiments "use_runner_v2"

Substitua:

  • PIPELINE: o arquivo de código-fonte do pipeline
  • PROJECT: o nome do projeto do Google Cloud.
  • BUCKET: o bucket do Cloud Storage.
  • REGION: uma região do Dataflow, por exemplo, us-central1. Selecione uma `REGION` que tenha zonas com suporte para GPU_TYPE. O Dataflow atribui automaticamente workers a uma zona com GPUs nessa região.
  • IMAGE: o caminho do Artifact Registry da imagem do Docker
  • DISK_SIZE_GB: tamanho do disco de inicialização de cada VM de worker. Por exemplo, 50
  • GPU_TYPE: um tipo de GPU disponível. Por exemplo, nvidia-tesla-t4.
  • GPU_COUNT: número de GPUs a serem anexadas a cada VM de worker. Por exemplo, 1

Verificar o job do Dataflow

Para confirmar que o job usa VMs de worker com GPUs, siga estas etapas:

  1. Verifique se os workers do Dataflow para o job foram iniciados.
  2. Durante a execução de um job, encontre uma VM de worker associada a ele.
    1. No comando Pesquisar produtos e recursos, cole o ID do job.
    2. Selecione a instância de VM do Compute Engine associada ao job.

Também é possível encontrar uma lista de todas as instâncias em execução no console do Compute Engine.

  1. No console do Google Cloud, acesse a página Instâncias de VMs.

    Acessar instâncias de VM

  2. Clique em Detalhes da instância de VM.

  3. Verifique se a página de detalhes tem uma seção GPUs e se as GPUs estão anexadas.

Se o job não foi iniciado com GPUs, verifique se a opção de serviço worker_accelerator está configurada corretamente e visível na interface de monitoramento do Dataflow em dataflow_service_options. A ordem dos tokens nos metadados do acelerador é importante.

Por exemplo, uma opção de pipeline dataflow_service_options na interface de monitoramento do Dataflow pode ser assim:

['worker_accelerator=type:nvidia-tesla-t4;count:1;install-nvidia-driver', ...]

Ver utilização da GPU

Para ver a utilização da GPU nas VMs de worker, siga estas etapas:

  1. No Console do Google Cloud, acesse Monitoring ou use o seguinte botão:

    Acessar Monitoring

  2. No painel de navegação do Monitoring, clique em Metrics Explorer.

  3. Em Tipo de recurso, especifique Dataflow Job. Para a métrica, especifique GPU utilization ou GPU memory utilization, dependendo da métrica que você quer monitorar.

Para mais informações, consulte Metrics Explorer.

Ativar o NVIDIA Multi-Processing Service

Em pipelines Python executados em workers com mais de uma vCPU, é possível melhorar a simultaneidade para operações de GPU ativando o NVIDIA Multi-Process Service (MPS). Para mais informações e etapas para usar o MPS, consulte Melhorar o desempenho em uma GPU compartilhada usando o NVIDIA MPS.

Usar GPUs com o Dataflow Prime

O Dataflow Prime permite solicitar aceleradores para uma etapa específica do pipeline. Para usar GPUs com o Dataflow Prime, não use a opção de pipeline --dataflow-service_options=worker_accelerator. Em vez disso, solicite as GPUs com a dica de recurso accelerator. Para mais informações, consulte Usar dicas de recursos.

Resolver problemas do job do Dataflow

Se você encontrar problemas ao executar o job do Dataflow com GPUs, consulte Resolver problemas do job da GPU do Dataflow.

A seguir