Explorando a Memória de Banda Larga (MCDRAM) do Intel® Xeon Phi™ Knights Landing no NCC - UNESP

Explorando a Memória de Banda Larga (MCDRAM) do

Intel® Xeon Phi™ Knights Landing no NCC – UNESP

Daniel Massaru Katsurayama

Jairo Panetta

Pedro Pais Lopes

Simone Shizue Tomita Lima

Finalidades

Explicar como utilizar os nós contendo Intel® Xeon Phi™ Knights Landing do NCC–UNESP e demonstrar como utilizar a memória de banda larga (MCDRAM) desse processador para acelerar uma computação real.

Sobre o conjunto de nós acelerados do NCC – UNESP

Os nós computacionais acelerados do Núcleo de Computação Científica da UNESP (NCC-UNESP) contem a primeira geração de processadores Intel® Xeon Phi™ (denominada Knights Corner ou KNC). Os nós phi01, phi02 e phi03 com tais processadores e experiências no seu uso estão descritos em “Tutorial para uso dos nós acelerados por Intel® Xeon Phi™ no NCC-Unesp”, acessível on-line.

Esse conjunto de nós contendo processadores Intel® Xeon Phi™ foi ampliado. O novo nó computacional phi04 contém um exemplar da segunda geração de processadores Intel® Xeon Phi™ (denominada Knights Landing ou KNL). A Tabela 1 contrasta os componentes desses nós.

 

Tabela 1: Componentes dos nós acelerados phi01, phi02, phi03 e do nó phi04 do NCC-Unesp

Nó computacional

phi01

phi02

phi03

phi04

Trecho com

Processadores

Intel®

Xeon®

Quantos Processadores

2

2

2

-

Identificação

E5-2699v3

E5-2670

E5-2699v3

-

Núcleos Físicos por Processador

18

8

18

-

Frequência

2,3GHz

2,6GHz

2,3GHz

-

Memória Central

128GB

64GB

128GB

-

Trecho com

Processadores

Intel®

Xeon

Phi™

Quantos Processadores

5

2

4

1

Identificação

5110P

3120A

7120P

7250

Núcleos Físicos por Processador

60

57

61

68

Frequência

1,0GHz

1,1GHz

1,2GHz

1,4GHz

Memória por Processador

8GB

6GB

16GB

192GB

MCDRAM

-

-

-

16GB

I/O

Memória SSD

-

1,2TB

1,2TB

-

Disco SATA

4TB

4TB

4TB

2TB

Conexão de Rede

Ethernet

2x Gigabit

2x Gigabit

2x Gigabit

2x Gigabit

InfiniBand

-

40 Gb/s QDR

40 Gb/s QDR

-

 

 

A segunda geração dessa família de processadores é totalmente diferente da primeira geração. O KNL foi projetado para ter a capacidade de ser um processador autônomo, enquanto o KNC é obrigatoriamente um acelerador de outro processador. O KNL pode carregar diretamente um sistema operacional completo, como no caso do phi04. Por exemplo, ssh para phi04 é atendido pelo KNL, enquanto o mesmo comando para o phi03 é atendido pelo processador Intel® Xeon®. Aplicações podem ser editadas, compiladas e enviadas para execução diretamente no KNL do phi04, enquanto no phi03 essas operações eram executadas no processador Intel® Xeon® (doravante denominado host) que controlava o KNC (doravante denominado device). Em suma, o KNL exerce as funções do host e do device.

A hierarquia de memória do KNL é substancialmente diferente da hierarquia de memória do KNC. Uma das novidades introduzidas pelo KNL é a presença de memória de banda larga (Multi Channel Dynamic Random Access Memory, MCDRAM). Essa memória tem o potencial de acelerar computações, pois sua velocidade de acesso (superior a 450 GB/s) é da ordem de cinco vezes mais rápida que a velocidade de acesso da memória usual (Double Data Rate 4th generation random access memory, DDR4), da ordem de 90GB/s. Entretanto, a MCDRAM é substancialmente menor que a DDR (16GB versus 192GB no phi04) como retratado na Tabela 1. Ainda mais, a capacidade da MCDRAM não pode ser alterada (pois está localizada “no pacote”, ou seja, no invólucro do KNL) enquanto a capacidade da DDR4 pode ser ampliada até 384GB, pois é externa ao invólucro do KNL.

A aplicação alvo

Este trabalho documenta nossa experiência em portar, executar e otimizar uma aplicação científica para o phi04. A aplicação científica alvo é o protótipo da dinâmica futura do BRAMS, modelo meteorológico regional utilizado diariamente em produção no Centro de Previsão de Tempo e Estudos Climáticos (CPTEC) do INPE. Essa aplicação contém da ordem de 110.000 linhas de código fonte em Fortran. Ela foi alvo de trabalhos anteriores, incluindo o porte e avaliação de desempenho para os processadores do nó phi03.

Para comparar o desempenho desses nós na aplicação alvo, reportamos inicialmente o desempenho da aplicação no phi03. A Figura 1 abaixo apresenta o tempo de execução (em segundos) e o speedup dessa aplicação no host e no device do phi03, variando o número de processos MPI de 1 a 200 com passo unitário. Essas execuções simularam vinte e quatro horas de integração temporal com passo de tempo de 60 segundos sobre uma grade tridimensional de 60 x 60 pontos na superfície do terreno e 35 níveis verticais.

 

 

Figura 1: Tempo de Execução em segundos (à esquerda) e Speedup nos Processadores do phi03 (à direita)

Os tempos de execução nos dois processadores inicialmente decrescem com o aumento do número de processos MPI, atingem tempo mínimo e crescem posteriormente. As diferenças dos tempos de execução decorrem naturalmente das diferenças de arquitetura dos dois processadores. Enquanto os dois processadores host contém 36 núcleos físicos (em conjunto) e operam em frequência maior (2,3GHz), o device utilizado isoladamente contém 68 núcleos físicos mas opera em frequência menor (1,2GHz). Dessa forma, é natural que o menor tempo de execução no host (10,9s) ocorra com menos processos MPI (36) do que no device (116). Também é natural que o speedup no device seja maior que no host com o mesmo número de processos MPI. Entretanto, o host obteve o menor tempo de execução em geral (10,9s no host contra 38,4s no device), mostrando que a aplicação não conseguiu compensar a maior frequência de operação do host pelo maior número de núcleos do device.

Compilação e Execução no phi04

Não é necessário qualquer ajuste no ambiente de software do phi04 para compilar e executar programas. Os compiladores geram código para o KNL sem que seja necessário utilizar qualquer chave de compilação, conforme os exemplos a seguir.

 

Compilação do programa serial exemplo.c no phi04, gerando o programa exemplo.exe: 

   icc –o exemplo.exe exemplo.c

Compilação do programa paralelo (MPI) exemplo_mpi.c no phi04, gerando o programa exemplo_mpi.exe:

   mpiicc –o exemplo_mpi.exe exemplo_mpi.c

 

Para produzir código otimizado no phi04, recomendamos o uso de chaves de compilação que ativam otimização agressiva e geram as instruções vetoriais próprias do KNL (-O3 e -xMIC-AVX512). A dinâmica do BRAMS foi compilada dessa forma no phi04. Em contraste, os tempos de execução no phi03 aqui reportados foram obtidos com chaves de compilação similares (-O3 –xCORE-AVX2 no host e –mmic –O3 –xCORE-AVX512 para o device).

Execuções no phi04 são imediatas, pois disparadas no próprio processador, conforme os exemplos a seguir.

 

Execução de programa sequencial no phi04:

   ./exemplo.exe

Execução de programa paralelo MPI no phi04:

    mpirun –n <numero de processos> ./exemplo_mpi.exe

 

Resultados Iniciais

Executamos o protótipo da dinâmica no phi04 com a mesma configuração das execuções no phi03. Utilizamos o mesmo programa fonte e as chaves de compilação acima descritas. Executamos de 1 a 200 processos MPI com passo unitário. Para facilitar a comparação entre as execuções nos dois nós, a Figura 2 apresenta os tempos de execução (em segundos) e os speedup nos três processadores dos dois nós computacionais.

 

Figura 2: Tempo de Execução em segundos (à esquerda) e Speedup nos Processadores do phi03 e do phi04 (à direita)

A segunda geração de processadores Intel® Xeon Phi™ (KNL) mostrou-se substancialmente mais rápida que a primeira geração (KNC) nesta aplicação. O menor tempo de execução no KNL foi 10,3s contra 38,4s no KNC. É notável que o KNL foi ainda mais rápido que o par de hosts Intel® Xeon® E5-2699v3 do phi03 (10,3s contra 10,9s).

O tempo mínimo no KNL ocorreu com 67 processos MPI, muito próximo ao número de núcleos físicos desse processador (68). Entretanto, o speedup com 67 processos MPI no KNL foi inferior ao speedup com o mesmo número de processos MPI no KNC (31,9 contra 37,2, respectivamente). Ainda mais, o speedup no KNC continua a aumentar com o aumento do número de processos MPI, enquanto que no KNL o speedup decresce na mesma circunstância.

Memória MCDRAM e seus Modos de Uso

As características computacionais da aplicação são favoráveis ao uso da memória MCDRAM por pelo menos três motivos.

O primeiro motivo é que a aplicação requer pouca memória na configuração testada. Execuções sequenciais utilizaram 95MB. Consequentemente, a quantidade de memória necessária é menor que a capacidade da MCDRAM (16GB) mas é muito maior que a capacidade dos caches internos aos núcleos (1MB de cache L2 e 32KB de cache L1 para dados).

O segundo motivo são as repetidas referencias à mesma posição de memória em instantes distintos da computação, tanto em um único passo de tempo quanto em passos distintos. Consequentemente, dados terão de ser trazidos da memória para os caches internos múltiplas vezes.

O terceiro motivo é a baixa quantidade de computações ponto flutuante realizada por acesso à memória principal. A velocidade dessa computação é limitada pela velocidade de acesso à memória, não pela velocidade de execução das operações ponto flutuante.

Vejamos então como utilizar a memória MCDRAM nessa computação.

A arquitetura de memória do KNL permite utilizar a memória MCDRAM de três formas: como cache da memória DDR4, como memória usual em excesso à memória DDR4 ou parcialmente em cada uma dessas duas formas.

No primeiro caso (denominado cache mode) a MCDRAM atua como cache de nível mais alto da memória DDR4. Neste modo, a quantidade de memória real disponível é a da DDR4. Quando um núcleo computacional busca o conteúdo de uma posição de memória, esta é procurada nos caches L1, L2 e na MCDRAM antes da DDR4.

No segundo caso (denominado flat mode) a MCDRAM é adicionada à DDR4, de forma que a quantidade de memória real disponível é a soma das capacidades dessas memórias. Quando um núcleo computacional busca o conteúdo de uma posição de memória, esta é procurada nos caches L1 e L2 e caso não seja encontrada é procurada ou na memória DDR4 ou na memória MCDRAM.

No terceiro caso (denominado hybrid mode) um trecho da memória MCDRAM é utilizado como cache de nível mais alto e o outro trecho como memória real.

Usuários não conseguem alterar a forma de uso da memória. Essa é uma decisão tomada pelo administrador do sistema e armazenada na BIOS. Durante as execuções descritas neste trabalho o nó phi04 estava configurado em flat mode. Ou seja, a memória real disponível é a soma das memórias DDR4 e MCDRAM.

Arquitetura de Memória do KNL

O KNL possui arquitetura de memória NUMA (Non-Uniform Memory Access). Esse tipo de arquitetura de memória é comum aos processadores atuais. Significa que o tempo de acesso de um núcleo computacional a uma posição de memória varia com o núcleo e com a posição de memória.

Em processadores modernos como o KNL, a memória acessível por um núcleo é organizada em conjuntos que o LINUX denomina nós (nodes). Alguns nós estão fisicamente (e logicamente) mais próximos a alguns núcleos do que a outros. Cada núcleo computacional pode acessar qualquer nó de memória, mas entre os núcleos computacionais e os nós de memória há uma rede de conexão que pode ser mais curta ou mais longa, passando por número variável de componentes. Esses são os motivos para o tempo de acesso (e outras características do acesso) variarem com o núcleo computacional e com a posição de memória.

Um comando LINUX que mostra este fato é numactl. Utilizando a opção –H (ou --hardware) esse comando mostra a quantidade de nós nesse sistema operacional, quais núcleos estão mais próximos de cada nó, a quantidade de memória em uso e disponível em cada nó e o tempo de transito entre cada conjunto de nós. Eis o resultado da execução desse comando no phi04:

 

phi04% numactl –-hardware

available: 8 nodes (0-7)

node 0 cpus: 0 1 2 3...

node 0 size: 49028 MB

node 0 free: 45325 MB

node 1 cpus: 18 19 20...

node 1 size: 49152 MB

node 1 free: 46745 MB

node 2 cpus: 36 37 38...

node 2 size: 49152 MB

node 2 free: 42195 MB

node 3 cpus: 52 53 54...

node 3 size: 49152 MB

node 3 free: 47001 MB

node 4 cpus:

node 4 size: 4096 MB

node 4 free: 3956 MB

node 5 cpus:

node 5 size: 4096 MB

node 5 free: 3959 MB

node 6 cpus:

node 6 size: 4096 MB

node 6 free: 3955 MB

node 7 cpus:

node 7 size: 4096 MB

node 7 free: 3958 MB

node distances:

node   0   1   2   3   4   5   6   7

  0:  10  21  21  21  31  41  41  41

  1:  21  10  21  21  41  31  41  41

  2:  21  21  10  21  41  41  31  41

  3:  21  21  21  10  41  41  41  31

  4:  31  41  41  41  10  41  41  41

  5:  41  31  41  41  41  10  41  41

  6:  41  41  31  41  41  41  10  41

  7:  41  41  41  31  41  41  41  10

 

Há oito nós de memória. Os quatro primeiros nós (0 – 3) contém os 192GB de DDR4. Os quatro nós restantes (4 – 7) contém os 16GB da MCDRAM. Todos os núcleos computacionais estão associados aos quatro primeiros nós.

A política de mapeamento de memória para os usuários do LINUX é “node local”. Isso significa que um processo do usuário executando em um núcleo computacional preferencialmente aloca memória do nó de memória associado ao núcleo.

Como a aplicação utiliza pouca memória, concluímos que toda a alocação de memória da aplicação utilizou a memória DDR4. Logo, a MCDRAM não foi utilizada.

Como Utilizar a Memória MCDRAM

O mesmo comando numactl permite alterar a política de mapeamento de memória, associando nós de memória especificados pelo usuário à núcleos computacionais. O comando “numactl –m <lista de nós> <processo>” associa a <lista de nós> aos núcleos computacionais durante a execução do <processo> e de seus filhos. Entretanto, durante a execução do <processo>, o núcleo computacional aloca memória exclusivamente do nó computacional especificado. Para usar este comando, o usuário deve ter certeza que a quantidade de memória utilizada pela aplicação é inferior à memória disponível no nó associado. É o caso desta aplicação.

As diversas formas de especificar a <lista de nós> estão descritas na documentação do LINUX (vide “man numactl”). Para associar os núcleos computacionais aos nós 4 a 7, basta utilizar o comando “numactl –m 4,5,6,7 <processo>”. Ou seja, basta executar o comando:

 

numactl –m 4,5,6,7 mpirun –n <numero de processos> ./dinamica.exe

 

na configuração de memória atual do phi04 para que a alocação de memória do protótipo da dinâmica do BRAMS seja feita exclusivamente da MCDRAM.

Observe a simplicidade da potencial otimização. A aplicação não é alterada, nem sequer recompilada. Entretanto, o usuário tem que garantir que a quantidade de memória utilizada pelo processo é inferior à disponível no nó de memória associado ao conjunto de núcleos computacionais.

O Impacto da Memória MCDRAM no Tempo de Execução

Executamos novamente o protótipo da dinâmica no phi04 mapeando a memória para a MCDRAM conforme acima descrito. Mantivemos a mesma configuração das execuções anteriores – a rigor, sequer recompilamos a aplicação. Executamos de 1 a 200 processos MPI com passo unitário.

A Figura 3 contém os tempos de execução (em segundos) e o speedup dessa execução e de algumas execuções anteriores, para permitir a comparação imediata. Contém os dados das execuções no host do phi03, no phi04 sem utilizar a MCDRAM e no phi04 utilizando a MCDRAM. O gráfico de tempos de execução exclui os tempos superiores a 50s para permitir comparação detalhada.

O ganho por utilizar a memória MDCRAM no phi04 é marcante. O menor tempo de execução com essa opção foi 7,8s com 135 núcleos. Em contraste, o menor tempo de execução sem essa opção no phi04 foi 10,3s com 67 núcleos. A redução do tempo de execução ao usar a MCDRAM ocorre com qualquer número de processos MPI, em menor ou maior escala. A curva de speedup retrata esse fato. O melhor speedup obtido anteriormente, sem utilizar a MCDRAM, foi de 31,9 com 67 processos MPI. Utilizando a MCDRAM o speedup passou para 40,5 com o mesmo número de processos MPI e o melhor speedup obtido foi 43,1 com 135 núcleos.

O ganho é admirável.

 

 

Figura 3: Tempo de Execução em segundos (à esquerda) e Speedup no host e no phi04 com e sem acessar a MCDRAM (à direita)

Conclusões e Material para Aprofundamento

O uso da memória MCDRAM foi extremamente favorável nesta aplicação. Sem qualquer alteração no programa fonte ou sequer recompilando a aplicação, os tempos de execução foram substancialmente reduzidos pelo uso dessa memória.

Novamente, reforçamos o fato que as características da aplicação permitem o uso simplificado da MCDRAM. Não são todas as aplicações que se beneficiam da MCDRAM. Dentre o conjunto de aplicações que se beneficiam da MCDRAM, as modificações necessárias para seu uso podem ser substancialmente maiores. Por exemplo, este procedimento não é aplicável em aplicações que utilizam quantidade de memória superior à disponível na MCDRAM. Entretanto, se o trecho da aplicação mais demandante de tempo (“hot spot”) utilizar quantidade de memória inferior à disponível na MCDRAM, talvez seja vantajoso alocar os objetos utilizados pelo hot spot na MCDRAM. Para tanto é necessário alterar o programa fonte, utilizando biblioteca específica para alocação de memória.

O procedimento para esse caso está descrito em “MCDRAM as High-Bandwidth Memory in Knights Landing Processors: Developer’s Guide”, escrito por Andrey Vladimirov e Ryo Asai da Colfax International, disponível on-line. Esse trabalho explica como utilizar a MCDRAM nos diversos modos de operação do KNL.

Introdução concisa mas profunda à arquitetura NUMA é o tema de “NUMA (Non-Uniform Memory Access): An Overview”, escrita por Christoph Lameter, publicada na ACM Queue, também disponível on-line.

O Intel Developer Zone contém diversas publicações muito úteis ao desenvolvedor interessado no uso do MCDRAM. Em particular, sugerimos o vídeo “MCDRAM on 2nd Generation Intel Xeon Phi Processor” por Chris Cantalupo, Karthik Raman e Ruchira Sasanka, bem como o tutorial associado à apresentação, disponível em https://software.intel.com/en-us/articles/mcdram-high-bandwidth-memory-on-knights-landing-analysis-methods-tools.

 

 

For more complete information about compiler optimizations, see our Optimization Notice.