Anexar GPUs a clusters

O Serviço Gerenciado para Apache Spark permite que as unidades de processamento gráfico (GPUs, na sigla em inglês) sejam anexadas aos nós mestre e de trabalho do Google Compute Engine em um cluster do Serviço Gerenciado para Apache Spark. Use essas GPUs para acelerar cargas de trabalho específicas nas instâncias, como machine learning e processamento de dados.

Para mais informações sobre o que pode ser feito com as GPUs e que tipos de hardware de GPU estão disponíveis, leia GPUs no Google Compute Engine.

Antes de começar

  • As GPUs exigem drivers e softwares especiais. Esses itens são pré-instalados nas imagens -ml do Serviço Gerenciado para Apache Spark (recomendamos o uso dessas imagens) e podem ser instalados manualmente quando e se necessário.-ml
  • Leia sobre preços de GPU no Google Compute Engine para entender o custo de usar GPUs nas instâncias.
  • Leia sobre restrições de instâncias com GPUs para saber como essas instâncias funcionam de maneira diferente da maioria das instâncias não GPU.
  • Verifique a página de cotas do projeto para garantir que você tenha uma cota de GPU suficiente (NVIDIA_T4_GPUS, NVIDIA_P100_GPUS ou NVIDIA_V100_GPUS) disponível no projeto. Se as GPUs não estiverem listadas nessa página ou se você precisar de cotas complementares, solicite um aumento de cota.

Tipos de GPUs

Os nós do Serviço Gerenciado para Apache Spark são compatíveis com os tipos de GPU a seguir. Especifique o tipo de GPU ao anexar GPUs ao cluster do Serviço Gerenciado para Apache Spark.

  • nvidia-tesla-l4 - NVIDIA® Tesla® L4
  • nvidia-tesla-a100 - NVIDIA® Tesla® A100
  • nvidia-tesla-p100 - NVIDIA® Tesla® P100
  • nvidia-tesla-v100 - NVIDIA® Tesla® V100
  • nvidia-tesla-p4 - NVIDIA® Tesla® P4
  • nvidia-tesla-t4 - NVIDIA® Tesla® T4
  • nvidia-rtx-pro-6000 - NVIDIA® RTX® PRO 6000
  • nvidia-tesla-p100-vws - NVIDIA® Tesla® P100 Virtual Workstations
  • nvidia-tesla-p4-vws - NVIDIA® Tesla® P4 Virtual Workstations
  • nvidia-tesla-t4-vws - NVIDIA® Tesla® T4 Virtual Workstations

Anexar GPUs a um cluster

Para anexar GPUs a um cluster do Serviço Gerenciado para Apache Spark, ao criar o cluster você deve especificar uma imagem -ml (recomendado) ou usar uma ação de inicialização para instalar drivers de GPU. Os exemplos a seguir especificam a 2.3-ml-ubuntu imagem ao criar um cluster.

Google Cloud CLI

Para anexar GPUs aos nós de worker principais e secundários em um cluster do Serviço Gerenciado para Apache Spark, crie o cluster usando as gcloud dataproc clusters create ‑‑master-accelerator, ‑‑worker-accelerator e ‑‑secondary-worker-accelerator flags. Essas flags usam os seguintes valores:

  • O tipo de GPU a ser anexada a um nó
  • O número de GPUs a serem anexadas ao nó

O tipo de GPU é obrigatório, e o número de GPUs é opcional. O padrão é uma GPU.

Exemplo:

gcloud dataproc clusters create cluster-name \
    --image-version=2.3-ml-ubuntu \
    --region=region \
    --master-accelerator type=nvidia-tesla-t4 \
    --worker-accelerator type=nvidia-tesla-t4,count=4 \
    --secondary-worker-accelerator type=nvidia-tesla-t4,count=4 \
    ... other flags

API REST

Para anexar GPUs aos nós de worker principais e secundários em um cluster do Serviço Gerenciado para Apache Spark, preencha no InstanceGroupConfig.AcceleratorConfig acceleratorTypeUri e acceleratorCount campos como parte da solicitação de API cluster.create. Esses campos usam os seguintes valores:

  • O tipo de GPU a ser anexada a um nó
  • O número de GPUs a serem anexadas ao nó

Console

Para anexar GPUs aos nós de worker principais e secundários em um cluster do Serviço Gerenciado para Apache Spark, siga estas etapas:

  1. Abra a página Criar um cluster do Serviço Gerenciado para Apache Spark no Compute Engine.
  2. Selecione o painel Configurar nós.
  3. Nas seções Nó mestre, Nós de worker e Nós de worker secundários, em Plataforma de CPU e GPU > GPUs, especifique o número de GPUs e o tipo de GPU dos nós.

Instalar os drivers da GPU

Os drivers de GPU são necessários para usar GPUs anexadas aos nós do Serviço Gerenciado para Apache Spark. Como alternativa ao uso dos drivers de GPU instalados nas imagens -ml do Serviço Gerenciado para Apache Spark, você pode usar as seguintes ações de inicialização para instalar drivers de GPU ao criar um cluster:

Verificar a instalação do driver da GPU

Para verificar a instalação do driver da GPU em um cluster, conecte-se usando SSH ao nó mestre do cluster e execute o seguinte comando:

nvidia-smi

Se o driver estiver funcionando corretamente, a saída exibirá a versão do driver e as estatísticas da GPU. Consulte Verificar a instalação do driver da GPU.

Configuração do Spark

Ao enviar um job ao Spark, use a configuração do Spark spark.executorEnv propriedade de ambiente de execução com a variável de ambiente LD_PRELOAD para pré-carregar as bibliotecas necessárias.

Exemplo:

gcloud dataproc jobs submit spark --cluster=CLUSTER_NAME \
  --region=REGION \
  --class=org.apache.spark.examples.SparkPi \
  --jars=file:///usr/lib/spark/examples/jars/spark-examples.jar \
  --properties=spark.executorEnv.LD_PRELOAD=libnvblas.so,spark.task.resource.gpu.amount=1,spark.executor.resource.gpu.amount=1,spark.executor.resource.gpu.discoveryScript=/usr/lib/spark/scripts/gpu/getGpusResources.sh

Exemplo de job da GPU

É possível testar GPUs no Serviço Gerenciado para Apache Spark executando qualquer um dos seguintes jobs, que se beneficiam quando executados com GPUs:

  1. Execute um dos exemplos de Spark ML.
  2. Execute o seguinte exemplo com spark-shell para executar uma computação de matriz:
import org.apache.spark.mllib.linalg._
import org.apache.spark.mllib.linalg.distributed._
import java.util.Random

def makeRandomSquareBlockMatrix(rowsPerBlock: Int, nBlocks: Int): BlockMatrix = {
  val range = sc.parallelize(1 to nBlocks)
  val indices = range.cartesian(range)
  return new BlockMatrix(
      indices.map(
          ij => (ij, Matrices.rand(rowsPerBlock, rowsPerBlock, new Random()))),
      rowsPerBlock, rowsPerBlock, 0, 0)
}

val N = 1024 * 4
val n = 2
val mat1 = makeRandomSquareBlockMatrix(N, n)
val mat2 = makeRandomSquareBlockMatrix(N, n)
val mat3 = mat1.multiply(mat2)
mat3.blocks.persist.count
println("Processing complete!")

A seguir