Tutorial para uso dos nós acelerados por Intel® Xeon® Phi™ no NCC-Unesp

Daniel Massaru Katsurayama
Jairo Panetta
Simone Shizue Tomita Lima

Finalidade

O Núcleo de Computação Científica da UNESP fornece serviços computacionais de grade utilizando clusters de nós computacionais. Além dos nós usuais dos clusters, o NCC possui três nós computacionais diferenciados, com alto poder computacional. Tais nós (phi01, phi02 e phi03) são munidos de processadores Intel® Xeon® acelerados por processadores Intel® Xeon Phi™ e serão denominados nós acelerados.

O uso adequado desses nós requer procedimentos específicos, distintos dos outros nós da grade. Este documento demonstra como utilizar esses nós. Relatamos a arquitetura dos nós e explicamos como ajustar o ambiente de software para utilizá-los. Em seguida, demonstramos como utilizar individualmente e em conjunto seus processadores em uma aplicação científica. Finalmente, mostramos como utilizar ferramentas de software da Intel para direcionar o processo de otimização da aplicação nesses processadores. A aplicação científica alvo é o BRAMS, modelo meteorológico regional utilizado diariamente em produção no Centro de Previsão de Tempo e Estudos Climáticos do INPE (http://brams.cptec.inpe.br).

Arquitetura dos Nós Acelerados

Os três nós (phi01, phi02 e phi03) são similares mas não são idênticos. A Figura 1 apresenta resumo didático, propositadamente simplificado, da arquitetura comum aos nós. A arquitetura pode ser dividida em duas partes: um trecho comum a todos os nós computacionais e um trecho acelerado.

O trecho comum é composto pela memória central, pelos processadores centrais Intel® Xeon® e por periféricos não retratados na figura. Os dois processadores centrais Intel® Xeon® endereçam a memória central do nó. Ao atingir o nó (por ssh, por exemplo), os usuários são atendidos por um núcleo computacional de um desses processadores, que se comporta como qualquer núcleo dos nós computacionais não acelerados, executando os comandos do sistema operacional demandados pelo usuário.

O trecho acelerado contém um conjunto de processadores Intel® Xeon® Phi™. Cada um desses processadores endereça memória própria. Esses processadores não têm acesso à memória central do nó e às memórias dos outros processadores – atuam unicamente sobre sua memória própria. Cada um desses processadores é gerenciado por um sistema operacional Linux que são identificados, internamente ao nó, por mic0, ..., mic<número>. Acesso a esses processadores é restrito a comandos internos a cada nó, sendo invisíveis externamente ao nó. Para atingir um desses processadores (por exemplo, mic0), a partir de um dos processadores centrais Intel® Xeon® basta executar ssh mic0. Em suma, o nó acelerado é munido de um sistema operacional Linux que opera sobre os dois processadores do trecho comum e um sistema operacional Linux para cada um dos processadores do trecho acelerado. Comunicação entre os sistemas operacionais dos trechos é feita de duas formas: pelo sistema de arquivos montado em todos os sistemas (por exemplo, o diretório home é visível em todos os processadores) e por mensagens que trafegam pela rede de comunicação.

 Arquitetura de um nó computacional acelerado

Figura 1: Arquitetura de um nó computacional acelerado

Os três nós possuem componentes em quantidades e capacidades distintas. A Tabela 1 apresenta as características dos componentes de cada um dos nós, organizada pelos trechos comuns e acelerados dos nós.

Tabela 1: Características dos nós computacionais acelerados

Nó computacionalphi01phi02phi03
Trecho comum:
Processadores
Centrais
Intel®
Xeon®
Quantos Processadores222
IdentificaçãoE5-2670E5-2699v3E5-2699v3
Núcleos Físicos por Processador81818
Frequência2,6GHz2,3GHz2,3GHz
Memória Central64GB128GB128GB
Trecho Acelerado:
Processadores
Intel®
Xeon®
Phi™
Quantos Processadores254
Identificação3120A5110P7120P
Núcleos Físicos por Processador576061
Frequência1,1GHz1,0GHz1,2GHz
Memória por Processador6GB8GB16GB
I/OMemória SSD-1,2TB1,2TB
Disco SATA4TB4TB4TB
Conexão de RedeEthernet2x Gigabit2x Gigabit2x Gigabit
InfiniBand-40 Gb/s QDR40 Gb/s QDR

A tabela mostra o poder computacional do trecho acelerado. A quantidade de núcleos físicos dos processadores Intel® Xeon® Phi™ é muito superior a quantidade de núcleos físicos dos processadores centrais Intel® Xeon®. Entretanto, cada núcleo físico do trecho acelerado é menos potente que seu correspondente no trecho comum, utiliza frequência significativamente inferior e acessa memoria restrita.

Cada um desses três nós acelerados possui de 130 a 280 núcleos físicos. Tal volume de núcleos só pode ser obtido pelo acoplamento de muitos nós não acelerados.

Configuração do Ambiente de Software dos Nós Acelerados

O uso dos nós acelerados requer configurar o ambiente de software para habilitar o uso de compiladores, bibliotecas e ferramentas de desenvolvimento específicos desses nós. Esse conjunto de ferramentas de software faz parte do Intel Parallel Studio, instalado no diretório /opt/intel. Descrevemos a configuração necessária para acessar a versão 2016.1.056 do Intel Parallel Studio, a versão instalada nos nós acelerados quando este documento foi escrito.

Altere o arquivo .bashrc, existente no seu diretório home, para incluir o diretório da instalação dos compiladores Intel Fortran e Intel C/C++ na variável de ambiente PATH, permitindo o acesso direto a tais ferramentas. Basta editar .bashrc e inserir os comandos a seguir:

Editar, inserir(linhas abaixo) e salvar o .bashrc:

PATH=${PATH}:/opt/intel/bin:/opt/intel/impi:.
export I_MPI_MIC=enable
source /opt/intel/parallel_studio_xe_2016.1.056/bin/psxevars.sh intel64
source /opt/intel/impi/5.1.2.150/bin64/mpivars.sh

É necessário recarregar esse arquivo para que a atualização torne-se efetiva:

Digitar:

$ source .bashrc

Para obter execuções livre de senhas nos núcleos do trecho acelerado, é necessário criar uma chave pública de autenticação no diretório .ssh e copiá-la para os sistemas operacionais de todos os processadores dos trechos acelerados. Esta tarefa permite tráfego de comandos entre os diversos sistemas operacionais Linux no nó acelerado sem digitar senhas. 

  1. Gerar a chave publica digite:
     $ ssh-keygen -t rsa
  2. Digitar <enter> nas 2 vezes para “passphrase”.

  3. Copiar para os Nós-acelerados:
    $ ssh-copy-id localhost
  4. Digitar yes para “connecting (yes/no)” e <insira seu password>

  5. Acessar o sistema operacional de cada Intel® Xeon® Phi™ disponível via ssh (mic0, mic1, etc):
     $ ssh mic0 
  6. Digitar senha e depois sair do mic0 (por exit).

  7. Repetir os itens 5 e 6 para os demais mic(s)

Esse procedimento permite utilizar os núcleos de todos os sistemas operacionais desse nó em uma computação, livre de senhas.

Compilação de Aplicações Sequenciais e Paralelas (MPI)

A literatura técnica de nós acelerados utiliza o termo host para identificar os processadores do trecho comum e o termo device para identificar os processadores do trecho acelerado. Utilizaremos essa nomenclatura.

Os núcleos do host são distintos dos núcleos do device. Programas compilados para os núcleos do host não necessariamente executam corretamente nos núcleos do device e vice versa. Cada um desses núcleos requer compilação específica, embora utilizem os mesmos compiladores.

Todas as compilações devem ser feitas no host, quer para gerar código executável para o host quer para gerar código executável para o device. A trajetória dos compiladores (incluídas no PATH) encontra-se abaixo. 

C: /opt/intel/bin/icc  
C++: /opt/intel/bin/icpc 
​Fortran: /opt/intel/bin/ifort

Para compilar programa sequencial para o host, utilize o compilador para a linguagem do programa (C, C++, Fortran): 

Compilação do programa sequencial exemplo.c para o host, gerando o arquivo executável exemplo_xeon.x:

icc –o exemplo_xeon.x exemplo.c 

Para compilar programas paralelos (MPI) quer para o host quer para o device, é necessário invocar os mesmos compiladores do programa sequencial, incluindo chaves de compilação específicas para MPI. Essas chaves estão incluídas em um shell script exclusivo para MPI, disponível na trajetória abaixo, já incluída no PATH: 

C: /opt/intel/impi/5.1.2.150/bin64/mpiicc
C++: /opt/intel/impi/5.1.2.150/bin64/mpiicpc
Fortran: /opt/intel/bin/mpiifort

Para compilar programas paralelos (MPI) para o host, utilize o shell script correspondente à linguagem do programa:

Compilação do programa paralelo (MPI) exemplo_mpi.c para o host, gerando o arquivo executável exemplo_mpi_xeon.x:

mpiicc –o exemplo_mpi_xeon.x exemplo_mpi.c 

Por default, os compiladores geram código para os núcleos do host. Para execuções no device, é necessário instruir o compilador para gerar código executável para os núcleos do device. Isso é feito pela introdução da chave de compilação -mmic na invocação do compilador, quer em programas sequenciais quer em programas paralelos: 

Compilação do programa serial exemplo.c para o device, gerando o arquivo executável exemplo_mic.x: 

icc –mmic –o exemplo_mic.x exemplo.c 

Compilação do programa paralelo (MPI) exemplo_mpi.c para o device, gerando o arquivo executável exemplo_mpi_mic.x:

mpiicc –mmic –o exemplo_mpi_mic.x exemplo_mpi.c 

Os programas executáveis gerados para cada um dos processadores são diferentes entre si, pois ao indicar a chave “-mmic” o programa somente estará habilitado para usar o device (Intel® Xeon® Phi™). Entretanto se não houver essa chave de compilação o programa só estará habilitado para utilizar o host (Intel® Xeon®). Para utilizar os dois processadores simultaneamente, é necessário efetuar as duas compilações, gerando dois executáveis.

Execução de Aplicações Sequenciais e Paralelas

Para executar programas sequenciais, basta estar no sistema operacional do processador desejado e disparar o programa executável compilado para esse processador, visto que o sistema de arquivos visível no host também é visível no device. Dessa forma, programas compilados no sistema de arquivos do host para execução no device são visíveis no device. Utilizando os exemplos de compilação acima, seja o programa sequencial exemplo.c, compilado para o host gerando o arquivo exemplo_xeon.x e compilado para o device gerando o arquivo exemplo_mic.x. A execução desse programa no host é obtida pelo comando ./exemplo_xeon.x, disparado do sistema operacional do host, enquanto a execução desse programa no device é obtida pelo comando ./exemplo_mic.x, disparada do sistema operacional do device.:

Programas sequenciais executados no host:

./exemplo_xeon.x 

Programas sequenciais executados no device:

./exemplo_mic.x

Programas paralelos (MPI) podem ser executados exclusivamente nos núcleos do host, podem ser executados exclusivamente nos núcleos do device e podem ser executados simultaneamente nos núcleos do host e do device.

Na realidade, há três formas de utilizar os núcleos do device, denominadas modelos de execução:

  • Modelo offload: processos executam no host e enviam trechos da computação para execução no device;
  • Modelo nativo: processos executam apenas no device;
  • Modelo simétrico: processos executam tanto no host quanto no device.

Este documento trata apenas dos modelos nativo e simétrico. O modelo offload requer modificar o programa fonte, identificando quais trechos devem ser enviados para execução do device. Maiores informações sobre como preparar e executar um programa no modelo de execução offload podem ser obtidas em https://software.intel.com/en-us/articles/using-mpi-and-xeon-phi-offload-together .

Para executar programas paralelos exclusivamente no host, basta utilizar o shellscriptmpirun:

Execução de programa paralelo MPI exclusivamente no host:

mpirun –n <numero de processos> ./exemplo_mpi_xeon.x

Para executar programas paralelos utilizando os núcleos do device, quer no modelo nativo quer no modelo simétrico, basta usar o mesmo shellscriptmpirun, disparado do sistema operacional do host, informando quantos processos utilizar em cada processador e qual executável utilizar em cada processador:

Execução de programa paralelo MPI nos modos nativo e simétrico:

Modelo nativo no mic0 com 2 processos:

 mpirun –n 2 -host mic0 ./exemplo_mpi_mic.x

Modelo nativo no mic1 com 2 processos:

  mpirun –n 2 -host mic1 ./exemplo_mpi_mic.x

Modelo nativo no mic0 e no mic1 com 2 processos em cada mic:

 mpirun –n 2 -host mic0 ./exemplo_mpi_mic.x : -n 2 -host mic1 ./exemplo_mpi_mic.x

Modelo simetrico no host e mic1 com 2 processos em cada um:

mpirun –n 2 -host phi03 ./exemplo_mpi.x : -n 2 -host mic1 ./exemplo_mpi_mic.x

Obs: Note que para o modelo simetrico usamos programas executáveis diferentes

A sintaxe do mpirun para disparar execuções em mais de um processador requer uma lista de argumentos para cada processador. As listas são separadas por “:”. Cada lista contém o número de processos, o nome do processador (a rigor, do sistema operacional) e o executável. É fundamental utilizar o executável compilado para o processador correspondente (exemplo_mpi.x para o host e exemplo_mpi_mic.x para o device). Observe o uso dos dois executáveis distintos no modelo simétrico.

Avaliação de Desempenho Paralelo de uma Aplicação Real

Utilizando as informações de configuração do ambiente, do uso dos compiladores e das diferentes maneiras de executar programas MPI, partimos para demonstrar como avaliar o desempenho paralelo de uma aplicação científica real. A finalidade desta seção é demonstrar como proceder para avaliar o desempenho paralelo. A avaliação propriamente dita está fora do escopo deste trabalho, pois requer conhecimento específico da área da aplicação, da nomenclatura e dos detalhes da codificação.

Avaliaremos o desempenho de um protótipo da versão 6.0 do modelo de previsão de tempo  regional BRAMS (Brazilian developments on the Regional Atmospheric Modeling System: http://brams.cptec.inpe.br). A versão atual (BRAMS 5.2) possui centenas de milhares de linhas de código e está sendo modificada para ampliar sua escalabilidade paralela, dos atuais 10.000 núcleos utilizados operacionalmente para da ordem de 100.000 núcleos.

No jargão meteorológico, modelos de previsão de tempo possuem dois componentes denominados dinâmica e física. A dinâmica ocupa poucas dezenas de milhares de linhas de código, mas concentra as operações paralelas que limitam a escalabilidade. Por sua vez, a física ocupa a grande maioria das linhas de código mas seu paralelismo é simples, com escalabilidade próxima à perfeição.

Esta análise utiliza um protótipo da dinâmica futura do BRAMS 6.0, atualmente em elaboração. Por ser a análise de desempenho inicial do protótipo, restringimos propositadamente o número de núcleos ao mínimo. Visamos comparar a escalabilidade paralela dos dois processadores existentes no nó acelerado, o Intel® Xeon® e o Intel® Xeon® Phi™.

Compilamos o protótipo da dinâmica para os dois processadores, utilizando os comandos acima descritos, após ajustar a configuração do ambiente conforme descrito. Em seguida, executamos o protótipo da dinâmica em uma grade tridimensional de 60x60x35 pontos para 1, 2, 4, 8, 12 e 14 núcleos computacionais dos dois processadores.

Os gráficos de speedup e de eficiência a seguir mostram o desempenho do protótipo da dinâmica no modo nativo para os processadores Intel® Xeon® e Intel® Xeon® Phi™.

 Gráfico de Speedup do protótipo da Dinâmica do modelo BRAMS

Figura 2: Gráfico de Speedup do protótipo da Dinâmica do modelo BRAMS

 Gráfico de Eficiência do protótipo da Dinâmica do modelo BRAMS

Figura 3: Gráfico de Eficiência do protótipo da Dinâmica do modelo BRAMS

Em uma análise simplificada, os gráficos demonstram uma diferença de escalabilidade entre os dois processadores do nó, ressaltando melhor escalabilidade paralela do Intel® Xeon® Phi™. Nota-se deficiência em alguns pontos da curva de desempenho paralelo comparando o speed-up obtido com o speed-up perfeito (linha vermelha da Figura 3). As ferramentas de desenvolvimento da Intel serão utilizadas, em futuro próximo, para orientar a otimização paralela.

Uso de Ferramentas de Desenvolvimento da INTEL

Para exemplificar o uso das ferramentas de desenvolvimento da Intel, utilizaremos a versão estável e completa do BRAMS 5.2. Utilizaremos a ferramenta Intel® VTune Amplifier XE para analisar o desempenho de uma execução paralela do BRAMS 5.2 em um nó com processador Intel® Xeon®. A análise será realizada em duas etapas. Na primeira etapa coletaremos informações sobre as funções/subrotinas do BRAMS que consomem maior tempo de CPU e, na segunda etapa, invocaremos o Intel® VTune Amplifier GUI e faremos a interpretação dos resultados obtidos a partir dos dados coletados na primeira etapa. A finalidade deste trabalho é determinar quais são os trechos da aplicação que utilizam o maior tempo de execução. Na literatura técnica, esses trechos são denominados hotspots.

Coletando dados do tempo de execução

Para coletar dados detalhados de tempo de execução, atribuindo tempos de execução a cada trecho do programa, é necessário que os arquivos fonte estejam no mesmo diretório do arquivo executável. Como o programa fonte do BRAMS 5.2 está espalhado por dezenas de diretórios, compilamos o programa fonte na forma usual para, em seguida, copiar os arquivos fonte para o diretório do executável. Não foi necessário utilizar qualquer chave específica de compilação.

Para coletar os detalhes do tempo de execução paralela da aplicação, a execução do mpirun deve ser feita em conjunto com o Intel® VTune Amplifier CL. Utilizamos a seguinte linha de comando: 

mpirun –n <N> amplxe-cl –r <result> –collect <analtype> <myapp> [options]

Onde:

  • <N> é o número de processadores utilizados na rodada paralela MPI;
  • <result> é um nome escolhido para o resultado da análise. O Intel® VTune Amplifier irá criar um diretório contendo o resultado da rodada paralela, chamado <result>.<hostname>, onde <hostname> é o nome do processador onde a rodada foi realizada. Os dados serão agrupados (encapsulados) por processos (rank MPI) executados neste nó;
  • <analtype> é o tipo da análise a ser realizada;
  • <myapp> é o nome da aplicação paralela;
  • [options] são as opções usadas pela aplicação paralela.

Considerando, por exemplo, uma rodada paralela com 16 núcleos nos Intel® Xeon® do nó phi03, utilizamos a seguinte linha de comando no diretório de execução do BRAMS: 

mpirun -host phi03 -n 16 amplxe-cl -collect hotspots -r vtunebrams ./brams-5.2 -f RAMSIN_meteo-only

Será criado o diretório vtunebrams.phi03.ncc.unesp.br contendo os dados detalhados (denominados traços) da execução paralela do BRAMS.

Interpretando os dados do tempo de execução

Abra o Intel® VTune Amplifier GUI usando o diretório com os dados da execução paralela gerada na etapa anterior: 

$ amplxe-gui vtunebrams.phi03.ncc.unesp.br &

A Figura 4 apresenta um sumário desta execução contendo informações sobre a plataforma utilizada: uma máquina com sistema operacional Linux CentOS instalado, CPU Intel® Xeon E5/E7 v3, 2.3GHz. 

 Sumário (parte 1) do Intel® VTune Amplifier XE

Figura 4: Sumário (parte 1) do Intel® VTune Amplifier XE

O histograma apresentado na Figura 4 mostra que a execução do BRAMS teve baixo aproveitamento do paralelismo disponível no nó, pois não utilizamos todos os núcleos físicos e não utilizamos hiperthreading. Além disso, a execução paralela obteve uma média de uso de CPU (average CPU usage) de 13, valor pouco inferior ao número de núcleos físicos (16) alocados na execução paralela.

A Figura 5 apresenta mais informações sobre o sumário da execução paralela, mostrando que o BRAMS consumiu 1829.005s de tempo de CPU, incluindo o tempo consumido em todos os núcleos. O tempo efetivo de uso da CPU foi de 1504.510s, sendo que 0.030s deste tempo é considerado ocioso (idle). Os 324.495s restantes do tempo de CPU foram gastos em tempo de espera (veja seção Spin Time), mais precisamente em operações de comunicação MPI. 

 Sumário (parte 2) do Intel® VTune Amplifier XE

Figura 5: Sumário (parte 2) do Intel® VTune Amplifier XE

A seção Top Hotspots da Figura 5 mostra as funções/subrotinas do BRAMS que foram mais acessadas e que são candidatas a serem otimizadas para se obter um melhora no desempenho geral do modelo. Estas funções/subrotinas estão ordenadas pelo tempo de CPU, destaque para a função MPI_waitany(), integrante da biblioteca MPI, que ocupou o primeiro posto consumindo 236.519s do tempo de CPU. 

A lista de Hotsposts apresentada na Figura 5 é limitada, não sendo possível obter informações sobre outras funções/subrotinas. A Figura 6 apresenta a seção “Bottom-up” do Intel® VTune Amplifier que permite visualizar em mais detalhes outros Hotspots, ordenados por tempo de CPU:

 Hotspots e seus ‘Callers’ no Intel® VTune Amplifier XE

Figura 6: Hotspots e seus ‘Callers’ no Intel® VTune Amplifier XE

Observe na Figura 6 que a função MPI_waitany() tem o tempo computado quase na sua totalidade como tempo de comunicação MPI (233.529s). No entanto, o tempo efetivo de utilização desta função é mínimo, cerca de 0.180s. O foco incidirá nas funções/subrotinas que consomem maior tempo efetivo de uso da CPU. Como exemplo, considere a subrotina reftra_sw() que consome 83.182s e faz parte do módulo da radiação RTM do BRAMS. Ao selecionar esta subrotina com duplo clique (em destaque laranja na Figura 6), é possível visualizar o trecho do código do BRAMS onde esta subrotina é invocada e que consome uma porcentagem elevada do tempo efetivo de utilização da CPU (veja Figura 7). 

 Hotspot identificado em trecho do código da Radiação RTM

Figura 7: Hotspot identificado em trecho do código da Radiação RTM

A Figura 7 mostra reftra_sw() sendo invocada 2 vezes no código fonte, sendo que na primeira chamada ela consumiu 2,7% do tempo efetivo de uso da CPU e, na segunda chamada o tempo consumido foi de aproximadamente 1,6% do tempo efetivo de uso da CPU. O destaque em vermelho (Poor) na barra de porcentagem do tempo efetivo de utilização mostra que esta subrotina é uma forte candidata a ser otimizada.

Navegando por outros Hotspots indicados pelo Intel® VTune Amplifier, é possível obter a porcentagem de tempo de CPU gasta por cada uma das funções/subrotinas do BRAMS. A Figura 8 apresenta a árvore de chamadas destas funções/subrotinas gerada com uso do software Doxygen. O gráfico desta figura foi combinado com as porcentagens de uso da CPU geradas pelo Intel® VTune Amplifier Profiler.

 Árvore de Chamadas (call graph) com dados coletados pelo Intel® VTune Amplifier XE

Figura 8: Árvore de Chamadas (call graph) com dados coletados pelo Intel® VTune Amplifier XE

A partir do gráfico da Figura 8 podemos selecionar os hotspots do BRAMS 5.2 classificando as funções/subrotinas em módulos da dinâmica e módulos da física e colocando-as em ordem decrescente da porcentagem do tempo efetivo de uso da CPU. Para os módulos da dinâmica, por exemplo, obtemos a Tabela 2:

Tabela 2: Funções/subrotinas dos módulos da dinâmica, (em ordem decrescrente de uso efetivo de CPU)

Função/subrotina

Módulo

Uso da CPU (%)

acoustic_new()
 

Acústica

 

5,78%

diffuse()
 

Turbulência

 

2,79%

advectc()
 

Advecção

 

1,77%

E no caso dos módulos da física, obtemos a Tabela 3:

Tabela 3: Funções/subrotinas dos módulos da física (em ordem decrescente de uso efetivo de CPU)

Função/subrotina

Módulo

Uso da CPU (%)

sfclyr_jules()
 

Superfície Jules

 

42,76%

 
rrtm_driver()
 

Radiação RTM

 

16,42%

micro_thompson()
 

Microfísica Thompson

 

11,06%

Consequentemente, as funções/subrotinas apresentadas nas Tabelas 2 e 3 são os pontos preferenciais para otimização do programa.

A partir dessa análise prévia e do uso aprofundado das ferramentas de software da Intel, será possível explorar caminhos para melhorar a velocidade sequencial da aplicação científica e sua escalabilidade. Soluções para os pontos de otimização foram iniciadas, novas implementações numéricas serão avaliadas, outras estruturas de dados serão propostas visando atingir o melhor desempenho da aplicação usando os processadores Intel.

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