6

Paralelismo de operadores e otimização de compilação

AI999第4课:现代计算底座与张量化并行演化
00:00

No EvoX , a unidade mínima de execução dos operadores evolutivos não é mais o "indivíduo", mas sim todo otensor de população: operadores como mutação, cruzamento e seleção cobrem todos os indivíduos em uma única chamada; sobre isso,a compilação de grafos computacionaisorganiza a sequência de operadores em um plano de execução otimizável, aumentando a eficiência de execução sem alterar a semântica do algoritmo.

Paralelismo de operadores e otimização de compilaçãoEvolução em lote por tensores · Compilação de grafos computacionais otimiza o plano de execuçãotensor de população[N, D] · Todos os indivíduosA dimensão dos indivíduos atua como dimensão de loteUma chamada cobre todos os indivíduosUma chamadacobre toda a populaçãoGrafo computacional dos operadores evolutivosMutaçãoCruzamentoSeleçãoDependências entre operadores → grafo computacionalOtimização global sobre todo o grafoEm vez de chamar implementações prontas operador por operadorCompilaçãoAntes da compilaçãoLoop por indivíduo · Muitos lançamentos de kernelsMuitos lançamentos de kernels, dimensão de lote igual a 1Fusão de operadores · Geração de kernels · Reúso de memória · Otimização de escalonamentoApós a compilaçãoGrafo computacional fundido · Poucos kernels eficientesUma passagem em lote conclui toda uma geração da evoluçãoComo calcular · Modo de execuçãoNúmero de kernelsTensores intermediáriosEstratégias de memória e escalonamentoA otimização atua apenas na camada de execução, sem alterar as regras de atualização dos operadoresO que calcular · Semântica do algoritmoMutaçãoCruzamentoSeleçãoCom a mesma semente aleatória, os resultados da evolução permanecem consistentes≠

Paralelismo de operadores: evolução em lote por tensores

  • Operadores em nível de tensor: mutação, cruzamento e seleção podem atuar diretamente sobre o tensor de população de formato [N, D] (N é o tamanho da população e D é a dimensão das variáveis de decisão); uma única chamada do operador cobre todos os N indivíduos.
  • Eliminação do loop por indivíduo: não é mais necessário escrever for ind in population: ind = mutate(ind) esse tipo de loop serial em Python/CPU, reduzindo a sobrecarga frequente de agendamento de funções e de chamadas ao framework.
  • Trocar dimensão de lote por throughput: quando a dimensão dos indivíduos atua como dimensão de lote, os operadores são executados no dispositivo de forma massivamente paralela, e o throughput da evolução em lote cresce com o tamanho da população.

Compilação de grafos computacionais: da sequência de operadores ao plano de execução

Organizando as dependências entre os operadores "mutação → cruzamento → seleção" em umgrafo computacional, o compilador pode realizar otimizações globais sobre todo o grafo, em vez de apenas chamar implementações prontas operador por operador:

  • Fusão de operadores: combina várias operações elemento a elemento (element-wise) em um único kernel, reduzindo a criação de tensores intermediários e as leituras e gravações repetidas.
  • Geração e escalonamento de kernels: gera kernels eficientes para o subgrafo fundido, concluindo a evolução de uma geração inteira com menos lançamentos de kernel.
  • Reúso de memória: planeja previamente os buffers para os resultados intermediários, reduzindo a sobrecarga adicional de alocação de memória de vídeo e movimentação de dados.

A eficiência mudou, a semântica não

É preciso distinguir"como calcular"de"o que calcular". O paralelismo de operadores e a otimização de compilação alteram apenas o modo de execução — número de kernels, escala dos tensores intermediários, estratégias de memória e escalonamento — sem mudar o significado lógico de mutação, cruzamento e seleção. A camada do algoritmo continua combinando os operadores conforme a semântica evolutiva; portanto, com a mesma semente aleatória, a trajetória evolutiva e os resultados antes e depois da otimização devem ser idênticos. Em resumo: a tensorização resolve "quão rápido o lote é calculado", a compilação de grafos computacionais resolve "quão otimizado é o escalonamento dos kernels", e "o que é calculado" permanece inalterado.

Equívocos comuns
Confundir a "tensorização" com "trocar para outro algoritmo evolutivo". A tensorização apenas aplica o mesmo operador a todo o tensor de população, sem alterar as regras de atualização entre os indivíduos; a otimização de compilação também não torna o algoritmo "mais inteligente". O que realmente exige atenção é não fazer validação de regressão após a otimização, confundindo diferenças de implementação com melhorias do algoritmo.