Skip to main content
NetApp artificial intelligence solutions
O português é fornecido por meio de tradução automática para sua conveniência. O inglês precede o português em caso de inconsistências.

Resultados dos testes

Colaboradores netapp-jsnyder

Usamos os scripts TeraSort e TeraValidate na ferramenta de benchmarking TeraGen para medir a validação de desempenho do Spark com as configurações E5760, E5724 e AFF-A800. Além disso, três casos de uso principais foram testados: pipelines Spark NLP e treinamento distribuído TensorFlow, treinamento distribuído Horovod e aprendizado profundo de vários trabalhadores usando Keras para previsão de CTR com DeepFM.

Para validação do E-Series e do StorageGRID , usamos o fator de replicação 2 do Hadoop. Para validação do AFF , usamos apenas uma fonte de dados.

A tabela a seguir lista a configuração de hardware para a validação de desempenho do Spark.

Tipo Nós de trabalho do Hadoop Tipo de unidade Unidades por nó Controlador de armazenamento

SG6060

4

SAS

12

Par único de alta disponibilidade (HA)

E5760

4

SAS

60

Par único de HA

E5724

4

SAS

24

Par único de HA

AFF800

4

SSD

6

Par único de HA

A tabela a seguir lista os requisitos de software.

Software Versão

RHEL

7,9

Ambiente de execução OpenJDK

1.8.0

VM do servidor OpenJDK de 64 bits

25,302

Git

2.24.1

GCC/G++

11.2.1

Fagulha

3.2.1

PySpark

3.1.2

SparkNLP

3.4.2

TensorFlow

2.9.0

Keras

2.9.0

Horovod

0.24.3

Análise de sentimento financeiro

Nós publicamos"TR-4910: Análise de sentimentos das comunicações com o cliente com a NetApp AI" , no qual um pipeline de IA de conversação de ponta a ponta foi construído usando o "Kit de ferramentas NetApp DataOps" , armazenamento AFF e sistema NVIDIA DGX. O pipeline executa processamento de sinal de áudio em lote, reconhecimento automático de fala (ASR), aprendizagem de transferência e análise de sentimentos, aproveitando o DataOps Toolkit, "NVIDIA Riva SDK" , e o "Estrutura do Tao" . Expandindo o caso de uso da análise de sentimentos para o setor de serviços financeiros, criamos um fluxo de trabalho SparkNLP, carregamos três modelos BERT para várias tarefas de PNL, como reconhecimento de entidade nomeada, e obtivemos sentimentos em nível de frase para as teleconferências de resultados trimestrais das 10 maiores empresas da NASDAQ.

O seguinte script sentiment_analysis_spark. py usa o modelo FinBERT para processar transcrições no HDFS e produzir contagens de sentimentos positivos, neutros e negativos, conforme mostrado na tabela a seguir:

-bash-4.2$ time ~/anaconda3/bin/spark-submit
--packages com.johnsnowlabs.nlp:spark-nlp_2.12:3.4.3
--master yarn
--executor-memory 5g
--executor-cores 1
--num-executors 160
--conf spark.driver.extraJavaOptions="-Xss10m -XX:MaxPermSize=1024M"
--conf spark.executor.extraJavaOptions="-Xss10m -XX:MaxPermSize=512M"
/sparkusecase/tr-4570-nlp/sentiment_analysis_spark.py hdfs:///data1/Transcripts/
> ./sentiment_analysis_hdfs.log 2>&1
real13m14.300s
user557m11.319s
sys4m47.676s

A tabela a seguir lista a análise de sentimento em nível de frase e teleconferência de resultados para as 10 maiores empresas da NASDAQ de 2016 a 2020.

Contagens de sentimentos e porcentagem Todas as 10 empresas AAPL AMD AMZN CSCO GOOGL INTC MSFT NVDA

Contagens positivas

7447

1567

743

290

682

826

824

904

417

Contagens neutras

64067

6856

7596

5086

6650

5914

6099

5715

6189

Contagens negativas

1787

253

213

84

189

97

282

202

89

Contagens não categorizadas

196

0

0

76

0

0

0

1

0

(contagens totais)

73497

8676

8552

5536

7521

6837

7205

6822

6695

Em termos de porcentagem, a maioria das frases ditas pelos CEOs e CFOs são factuais e, portanto, carregam sentimentos neutros. Durante uma teleconferência de resultados, os analistas fazem perguntas que podem transmitir sentimentos positivos ou negativos. Vale a pena investigar mais quantitativamente como o sentimento negativo ou positivo afeta os preços das ações no mesmo dia ou no dia seguinte de negociação.

A tabela a seguir lista a análise de sentimento em nível de frase para as 10 maiores empresas do NASDAQ, expressa em porcentagem.

Porcentagem de sentimento Todas as 10 empresas AAPL AMD AMZN CSCO GOOGL INTC MSFT NVDA

Positivo

10,13%

18,06%

8,69%

5,24%

9,07%

12,08%

11,44%

13,25%

6,23%

Neutro

87,17%

79,02%

88,82%

91,87%

88,42%

86,50%

84,65%

83,77%

92,44%

Negativo

2,43%

2,92%

2,49%

1,52%

2,51%

1,42%

3,91%

2,96%

1,33%

Sem categoria

0,27%

0%

0%

1,37%

0%

0%

0%

0,01%

0%

Em termos de tempo de execução do fluxo de trabalho, vimos uma melhoria significativa de 4,78x local modo para um ambiente distribuído no HDFS e uma melhoria adicional de 0,14% ao aproveitar o NFS.

-bash-4.2$ time ~/anaconda3/bin/spark-submit
--packages com.johnsnowlabs.nlp:spark-nlp_2.12:3.4.3
--master yarn
--executor-memory 5g
--executor-cores 1
--num-executors 160
--conf spark.driver.extraJavaOptions="-Xss10m -XX:MaxPermSize=1024M"
--conf spark.executor.extraJavaOptions="-Xss10m -XX:MaxPermSize=512M"
/sparkusecase/tr-4570-nlp/sentiment_analysis_spark.py file:///sparkdemo/sparknlp/Transcripts/
> ./sentiment_analysis_nfs.log 2>&1
real13m13.149s
user537m50.148s
sys4m46.173s

Como mostra a figura a seguir, o paralelismo de dados e modelos melhorou o processamento de dados e a velocidade de inferência do modelo distribuído do TensorFlow. A localização dos dados no NFS produziu um tempo de execução um pouco melhor porque o gargalo do fluxo de trabalho é o download de modelos pré-treinados. Se aumentarmos o tamanho do conjunto de dados de transcrições, a vantagem do NFS fica mais óbvia.

Tempo de execução do fluxo de trabalho de análise de sentimentos do Spark NLP.

Treinamento distribuído com desempenho Horovod

O comando a seguir produziu informações de tempo de execução e um arquivo de log em nosso cluster Spark usando um único master nó com 160 executores, cada um com um núcleo. A memória do executor foi limitada a 5 GB para evitar erros de falta de memória. Veja a seção"Scripts Python para cada caso de uso principal" para mais detalhes sobre o processamento de dados, treinamento do modelo e cálculo de precisão do modelo em keras_spark_horovod_rossmann_estimator.py .

(base) [root@n138 horovod]# time spark-submit
--master local
--executor-memory 5g
--executor-cores 1
--num-executors 160
/sparkusecase/horovod/keras_spark_horovod_rossmann_estimator.py
--epochs 10
--data-dir file:///sparkusecase/horovod
--local-submission-csv /tmp/submission_0.csv
--local-checkpoint-file /tmp/checkpoint/
> /tmp/keras_spark_horovod_rossmann_estimator_local. log 2>&1

O tempo de execução resultante com dez épocas de treinamento foi o seguinte:

real43m34.608s
user12m22.057s
sys2m30.127s

Foram necessários mais de 43 minutos para processar dados de entrada, treinar um modelo DNN, calcular a precisão e produzir pontos de verificação do TensorFlow e um arquivo CSV para resultados de previsão. Limitamos o número de períodos de treinamento a 10, que na prática geralmente é definido como 100 para garantir precisão satisfatória do modelo. O tempo de treinamento normalmente é escalonado linearmente com o número de épocas.

Em seguida, usamos os quatro nós de trabalho disponíveis no cluster e executamos o mesmo script em yarn modo com dados em HDFS:

(base) [root@n138 horovod]# time spark-submit
--master yarn
--executor-memory 5g
--executor-cores 1 --num-executors 160 /sparkusecase/horovod/keras_spark_horovod_rossmann_estimator.py
--epochs 10
--data-dir hdfs:///user/hdfs/tr-4570/experiments/horovod
--local-submission-csv /tmp/submission_1.csv
--local-checkpoint-file /tmp/checkpoint/
> /tmp/keras_spark_horovod_rossmann_estimator_yarn.log 2>&1

O tempo de execução resultante foi melhorado da seguinte forma:

real8m13.728s
user7m48.421s
sys1m26.063s

Com o modelo de Horovod e o paralelismo de dados no Spark, vimos uma aceleração de tempo de execução de 5,29x yarn contra local modo com dez épocas de treinamento. Isso é mostrado na figura a seguir com as legendas HDFS e Local . O treinamento do modelo DNN subjacente do TensorFlow pode ser ainda mais acelerado com GPUs, se disponíveis. Planejamos realizar esses testes e publicar os resultados em um futuro relatório técnico.

Nosso próximo teste comparou os tempos de execução com dados de entrada residindo em NFS versus HDFS. O volume NFS no AFF A800 foi montado em /sparkdemo/horovod nos cinco nós (um mestre, quatro trabalhadores) em nosso cluster Spark. Executamos um comando semelhante aos testes anteriores, com o --data- dir parâmetro agora apontando para a montagem NFS:

(base) [root@n138 horovod]# time spark-submit
--master yarn
--executor-memory 5g
--executor-cores 1
--num-executors 160
/sparkusecase/horovod/keras_spark_horovod_rossmann_estimator.py
--epochs 10
--data-dir file:///sparkdemo/horovod
--local-submission-csv /tmp/submission_2.csv
--local-checkpoint-file /tmp/checkpoint/
> /tmp/keras_spark_horovod_rossmann_estimator_nfs.log 2>&1

O tempo de execução resultante com NFS foi o seguinte:

real 5m46.229s
user 5m35.693s
sys  1m5.615s

Houve uma aceleração adicional de 1,43x, conforme mostrado na figura a seguir. Portanto, com um armazenamento all-flash da NetApp conectado ao seu cluster, os clientes aproveitam os benefícios da rápida transferência e distribuição de dados para fluxos de trabalho do Horovod Spark, alcançando uma aceleração de 7,55x em comparação à execução em um único nó.

Tempo de execução do fluxo de trabalho do Horovod Spark.

Modelos de aprendizado profundo para desempenho de previsão de CTR

Para sistemas de recomendação projetados para maximizar o CTR, você deve aprender interações de recursos sofisticados por trás dos comportamentos do usuário que podem ser calculados matematicamente da ordem mais baixa para a mais alta. Tanto as interações de recursos de baixa quanto de alta ordem devem ser igualmente importantes para um bom modelo de aprendizado profundo, sem distorção em relação a uma ou outra. Deep Factorization Machine (DeepFM), uma rede neural baseada em máquina de fatoração, combina máquinas de fatoração para recomendação e aprendizado profundo para aprendizado de recursos em uma nova arquitetura de rede neural.

Embora as máquinas de fatoração convencionais modelem interações de recursos em pares como um produto interno de vetores latentes entre recursos e possam, teoricamente, capturar informações de alta ordem, na prática, os profissionais de aprendizado de máquina geralmente usam apenas interações de recursos de segunda ordem devido à alta complexidade de computação e armazenamento. Variantes de redes neurais profundas como as do Google "Modelos largos e profundos" por outro lado, aprende interações de recursos sofisticados em uma estrutura de rede híbrida combinando um modelo linear amplo e um modelo profundo.

Há duas entradas para este Modelo Amplo e Profundo, uma para o modelo amplo subjacente e outra para o profundo, sendo que esta última parte ainda requer engenharia de recursos especializada e, portanto, torna a técnica menos generalizável para outros domínios. Diferentemente do modelo amplo e profundo, o DeepFM pode ser treinado eficientemente com recursos brutos sem qualquer engenharia de recursos, porque sua parte ampla e parte profunda compartilham a mesma entrada e o mesmo vetor de incorporação.

Primeiro processamos o Criteo train.txt (11 GB) em um arquivo CSV chamado ctr_train.csv armazenado em uma montagem NFS /sparkdemo/tr-4570-data usando run_classification_criteo_spark.py da seção"Scripts Python para cada caso de uso principal." Dentro deste script, a função process_input_file executa vários métodos de string para remover tabulações e inserir ',' como delimitador e '\n' como nova linha. Observe que você só precisa processar o original train.txt uma vez, para que o bloco de código seja mostrado como comentários.

Para os testes seguintes de diferentes modelos DL, usamos ctr_train.csv como arquivo de entrada. Em execuções de testes subsequentes, o arquivo CSV de entrada foi lido em um Spark DataFrame com esquema contendo um campo de 'label' , recursos densos inteiros ['I1', 'I2', 'I3', …, 'I13'] , e recursos esparsos ['C1', 'C2', 'C3', …, 'C26'] . A seguir spark-submit O comando recebe um CSV de entrada, treina modelos DeepFM com divisão de 20% para validação cruzada e escolhe o melhor modelo após dez períodos de treinamento para calcular a precisão da previsão no conjunto de teste:

(base) [root@n138 ~]# time spark-submit --master yarn --executor-memory 5g --executor-cores 1 --num-executors 160 /sparkusecase/DeepCTR/examples/run_classification_criteo_spark.py --data-dir file:///sparkdemo/tr-4570-data > /tmp/run_classification_criteo_spark_local.log 2>&1

Observe que, como o arquivo de dados ctr_train.csv for maior que 11 GB, você deve definir um espaço suficiente spark.driver.maxResultSize maior que o tamanho do conjunto de dados para evitar erros.

 spark = SparkSession.builder \
    .master("yarn") \
    .appName("deep_ctr_classification") \
    .config("spark.jars.packages", "io.github.ravwojdyla:spark-schema-utils_2.12:0.1.0") \
    .config("spark.executor.cores", "1") \
    .config('spark.executor.memory', '5gb') \
    .config('spark.executor.memoryOverhead', '1500') \
    .config('spark.driver.memoryOverhead', '1500') \
    .config("spark.sql.shuffle.partitions", "480") \
    .config("spark.sql.execution.arrow.enabled", "true") \
    .config("spark.driver.maxResultSize", "50gb") \
    .getOrCreate()

No acima SparkSession.builder configuração também habilitamos "Flecha Apache" , que converte um Spark DataFrame em um Pandas DataFrame com o df.toPandas() método.

22/06/17 15:56:21 INFO scheduler.DAGScheduler: Job 2 finished: toPandas at /sparkusecase/DeepCTR/examples/run_classification_criteo_spark.py:96, took 627.126487 s
Obtained Spark DF and transformed to Pandas DF using Arrow.

Após a divisão aleatória, há mais de 36 milhões de linhas no conjunto de dados de treinamento e 9 milhões de amostras no conjunto de teste:

Training dataset size =  36672493
Testing dataset size =  9168124

Como este relatório técnico se concentra em testes de CPU sem usar GPUs, é fundamental que você crie o TensorFlow com sinalizadores de compilador apropriados. Esta etapa evita invocar quaisquer bibliotecas aceleradas por GPU e aproveita ao máximo as instruções Advanced Vector Extensions (AVX) e AVX2 do TensorFlow. Esses recursos são projetados para cálculos algébricos lineares, como adição vetorizada, multiplicação de matrizes dentro de um treinamento DNN de propagação direta ou retropropagação. A instrução Fused Multiply Add (FMA) disponível com AVX2 usando registradores de ponto flutuante (FP) de 256 bits é ideal para códigos inteiros e tipos de dados, resultando em um aumento de velocidade de até 2x. Para códigos FP e tipos de dados, o AVX2 atinge 8% de aceleração em relação ao AVX.

2022-06-18 07:19:20.101478: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.

Para construir o TensorFlow a partir do código-fonte, a NetApp recomenda usar "Bazel" . Para nosso ambiente, executamos os seguintes comandos no prompt do shell para instalar dnf , dnf-plugins , e Bazel.

yum install dnf
dnf install 'dnf-command(copr)'
dnf copr enable vbatts/bazel
dnf install bazel5

Você deve habilitar o GCC 5 ou mais recente para usar os recursos do C++17 durante o processo de compilação, que é fornecido pelo RHEL com a Software Collections Library (SCL). Os seguintes comandos instalam devtoolset e GCC 11.2.1 em nosso cluster RHEL 7.9:

subscription-manager repos --enable rhel-server-rhscl-7-rpms
yum install devtoolset-11-toolchain
yum install devtoolset-11-gcc-c++
yum update
scl enable devtoolset-11 bash
. /opt/rh/devtoolset-11/enable

Observe que os dois últimos comandos habilitam devtoolset-11 , que usa /opt/rh/devtoolset-11/root/usr/bin/gcc (GCC 11.2.1). Além disso, certifique-se de que seu git a versão é maior que 1.8.3 (vem com o RHEL 7.9). Consulte isto "artigo" para atualização git para 2.24.1.

Presumimos que você já clonou o repositório mestre mais recente do TensorFlow. Em seguida, crie um workspace diretório com um WORKSPACE arquivo para compilar o TensorFlow a partir do código-fonte com AVX, AVX2 e FMA. Execute o configure arquivo e especifique o local binário correto do Python. "CUDA" está desabilitado para nossos testes porque não usamos uma GPU. UM .bazelrc o arquivo é gerado de acordo com suas configurações. Além disso, editamos o arquivo e configuramos build --define=no_hdfs_support=false para habilitar o suporte HDFS. Consulte .bazelrc na seção"Scripts Python para cada caso de uso principal," para uma lista completa de configurações e sinalizadores.

./configure
bazel build -c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-mfpmath=both -k //tensorflow/tools/pip_package:build_pip_package

Depois de criar o TensorFlow com os sinalizadores corretos, execute o script a seguir para processar o conjunto de dados Criteo Display Ads, treinar um modelo DeepFM e calcular a Área sob a Curva Característica Operacional do Receptor (ROC AUC) a partir das pontuações de previsão.

(base) [root@n138 examples]# ~/anaconda3/bin/spark-submit
--master yarn
--executor-memory 15g
--executor-cores 1
--num-executors 160
/sparkusecase/DeepCTR/examples/run_classification_criteo_spark.py
--data-dir file:///sparkdemo/tr-4570-data
> . /run_classification_criteo_spark_nfs.log 2>&1

Após dez períodos de treinamento, obtivemos a pontuação AUC no conjunto de dados de teste:

Epoch 1/10
125/125 - 7s - loss: 0.4976 - binary_crossentropy: 0.4974 - val_loss: 0.4629 - val_binary_crossentropy: 0.4624
Epoch 2/10
125/125 - 1s - loss: 0.3281 - binary_crossentropy: 0.3271 - val_loss: 0.5146 - val_binary_crossentropy: 0.5130
Epoch 3/10
125/125 - 1s - loss: 0.1948 - binary_crossentropy: 0.1928 - val_loss: 0.6166 - val_binary_crossentropy: 0.6144
Epoch 4/10
125/125 - 1s - loss: 0.1408 - binary_crossentropy: 0.1383 - val_loss: 0.7261 - val_binary_crossentropy: 0.7235
Epoch 5/10
125/125 - 1s - loss: 0.1129 - binary_crossentropy: 0.1102 - val_loss: 0.7961 - val_binary_crossentropy: 0.7934
Epoch 6/10
125/125 - 1s - loss: 0.0949 - binary_crossentropy: 0.0921 - val_loss: 0.9502 - val_binary_crossentropy: 0.9474
Epoch 7/10
125/125 - 1s - loss: 0.0778 - binary_crossentropy: 0.0750 - val_loss: 1.1329 - val_binary_crossentropy: 1.1301
Epoch 8/10
125/125 - 1s - loss: 0.0651 - binary_crossentropy: 0.0622 - val_loss: 1.3794 - val_binary_crossentropy: 1.3766
Epoch 9/10
125/125 - 1s - loss: 0.0555 - binary_crossentropy: 0.0527 - val_loss: 1.6115 - val_binary_crossentropy: 1.6087
Epoch 10/10
125/125 - 1s - loss: 0.0470 - binary_crossentropy: 0.0442 - val_loss: 1.6768 - val_binary_crossentropy: 1.6740
test AUC 0.6337

De maneira semelhante aos casos de uso anteriores, comparamos o tempo de execução do fluxo de trabalho do Spark com dados residentes em locais diferentes. A figura a seguir mostra uma comparação da previsão de CTR de aprendizado profundo para um tempo de execução de fluxos de trabalho do Spark.

Comparação da previsão de CTR de aprendizado profundo para um tempo de execução de fluxos de trabalho do Spark.