Pergunta

Já me pediram para medir o desempenho de um programa fortran que resolve equações diferenciais em um sistema multi-CPU. Meu empregador insiste que eu medir FLOP / s (operações por segundo flutuante) e comparar os resultados com benchmarks ( LINPACK ), mas eu não estou convencido de que é o caminho a percorrer, simplesmente porque ninguém pode me explicar o que é um FLOP é.

Eu fiz alguma pesquisa sobre o que exatamente um FLOP é e eu tenho algumas respostas muito contraditórias. Um dos mais populares respostas que recebi foi '1 FLOP = uma adição e uma operação de multiplicação. Isso é verdade? Se assim for, de novo, fisicamente, o que exatamente significa isso?

Qualquer método que eu acabar usando, ele tem que ser escalável. Algumas versões do código de sistemas com vários milhões de incógnitas resolver e leva dias para executar.

O que seria alguns outros, eficazes, maneiras de medir o desempenho no meu caso (resumo do meu caso ser 'código Fortran que faz um monte de cálculos aritméticos mais e outra vez durante dias a várias centenas de CPUs)?

Foi útil?

Solução

É uma medida bastante decente de desempenho, desde que você entenda exatamente o que ele mede.

FLOPS é, como o nome implica operações de ponto flutuante por segundo, exatamente o que constitui um FLOP pode variar de acordo com CPU. (Alguns de CPU pode executar adição e multiplicação como uma operação, outros não podem, por exemplo). Isso significa que, como medida de desempenho, é bastante próximo do hardware, o que significa que 1) você tem que saber o seu hardware para calcular o ideal flops na arquitetura dada, e você tem que saber o seu algoritmo e implementação de descobrir como muitos ops ponto flutuante que realmente consiste.

Em qualquer caso, é uma ferramenta útil para examinar o quão bem você utiliza a CPU. Se você conhece um desempenho teórico máximo da CPU em FLOPS, você pode trabalhar para fora como forma eficiente de utilizar unidades de ponto flutuante do CPU, que são muitas vezes um dos difícil de utilizar eficientemente. Um programa que é executado 30% do FLOPS a CPU é capaz, tem espaço para otimização. Um que roda a 70% provavelmente não vai ficar muito mais eficiente a menos que você alterar o algoritmo básico. Para algoritmos matemáticos-pesados ??como a sua, que é praticamente a forma padrão para medir o desempenho. Você poderia simplesmente medir quanto tempo um programa leva para executar, mas isso varia muito, dependendo da CPU. Mas se o seu programa tem uma utilização de CPU de 50% (em relação ao pico FLOPS count), que é um valor um pouco mais constante (que ainda vai variar entre radicalmente diferentes arquiteturas de CPU, mas é muito mais consistente do que o tempo de execução).

Mas saber que "meu CPU é capaz de X GFLOPS, e eu só estou realmente alcançar uma taxa de transferência de, digamos, 20% dos que" é muito informações valiosas em software de alto desempenho. Isso significa que algo outros do que os ops ponto flutuante está prendendo você, e impedindo as unidades FP de trabalhar de forma eficiente. E uma vez que as unidades do PQ constituem a maior parte do trabalho, significa que o software tem um problema.

É fácil de medir "Meu programa é executado em X minutos", e se você sentir que é inaceitável em seguida, com certeza, você pode ir "Eu me pergunto se eu posso cortar 30% de desconto que", mas você não sabe se isso é possível, a menos que você trabalha para fora exatamente quanto trabalho está sendo feito, e exatamente o que a CPU é capaz de, no máximo. Quanto tempo você quer gastar otimizar isso, se você ainda não sabe se o CPU é fundamentalmente capaz de executar qualquer mais instruções por segundo?

É muito fácil para evitar unidade FP da CPU seja utilizada de forma eficiente, por ter muitas dependências entre ops FP, ou por ter muitos ramos ou prevenir semelhante agendamento eficiente. E se é isso que está segurando sua implementação para trás, você necessidade para saber isso. Você precisa saber que "eu não estou recebendo o FP rendimento que deve ser possível, tão claramente outras partes do meu código estão impedindo FP instruções de estar disponível quando a CPU está pronto para emitir um".

Por que você precisa de outras formas de medir o desempenho? O que há de errado com apenas trabalhando o FLOPS contar como seu chefe lhe pediu para? ;)

Outras dicas

Eu apenas gostaria de acrescentar um par de pontos mais delicados:

  • divisão é especial. Uma vez que a maioria dos processadores pode fazer uma adição, comparação, ou multiplicação num único ciclo, aqueles são todos contados como um fracasso. Mas a divisão sempre leva mais tempo. Quanto tempo depende do processador, mas há uma espécie de padrão de fato na comunidade HPC para contar uma divisão de 4-flops.

  • Se um processador tem um fundido multiplicam-add instrução que faz uma multiplicação e uma adição de uma única instrução - geralmente A + B = C * - que a contagem como 2 operações .

  • Sempre ter cuidado na distinção entre de precisão simples flops e precisão dupla-flops . Um processador que é capaz de tantas gigaflops de precisão simples pode ser apenas capaz de uma pequena fracção do que muitos gigaflops dupla precisão. Os processadores AMD Athlon e Phenom geralmente podem fazer metade como muitos de precisão dupla-flops como precisão simples. Os processadores ATI FireStream geralmente podem fazer 1 / 5th o maior número de precisão dupla-flops como precisão simples. Se alguém está tentando vender-lhe um um pacote de software processador ou e eles só Citação fracassos sem dizer que, você deve chamá-los nele.

  • Os termos megaflop, gigaflop, teraflop, etc. são de uso comum. Referem-se a fatores de 1000 , Não 1024 . Por exemplo, um megaflop = 1000000 fracasso / seg não 1.048.576. Assim como com os tamanhos de unidade de disco, há alguma confusão sobre este assunto.

"comparar os resultados com benchmarks" e fazer o que?

FLOPS significa que você precisa

1) flops por alguma unidade de trabalho.

2) tempo para que unidade de trabalho.

Vamos dizer que você tem algum arquivo de entrada que faz 1.000 iterações através de algum loop. O laço é uma unidade acessível de trabalho. Ele é executado 1.000 vezes. Leva uma hora.

O circuito tem algumas adições e multiplica e algumas divisões e uma raiz quadrada. Você pode contar Adiciona, se multiplica e divide. Você pode contar isso na fonte, procurando +, * e /. Você pode encontrar a saída de linguagem assembly do compilador, e contá-los lá, também. Você pode obter números diferentes. Qual é a certa? Pergunte ao seu chefe.

Você pode contar as raízes quadradas, mas você não sabe o que realmente faz em termos de multiplica e adiciona. Então, você vai ter que fazer algo como referência multiplicam vs. raiz quadrada para ter uma noção de quanto tempo uma raiz quadrada leva.

Agora você sabe os fracassos em seu loop. E você sabe o tempo para executá-lo 1.000 vezes. Você sabe FLOPS por segundo.

Então você olha para LINPACK e achar que você está mais lento. O que agora? Seu programa não é LINPACK, e é mais lento do que LINPACK. As probabilidades são muito boas que seu código será mais lento. A menos que seu código foi escrito e otimizado em relação ao mesmo número de anos que uma LINPACK, você vai ser mais lento.

Aqui está a outra parte. Seu processador tem alguma classificação FLOPS definido contra vários benchmarks. Seu algoritmo não é um desses benchmarks, assim você ficar aquém dos benchmarks. Isto é ruim? Ou esta é a consequência óbvia de não ser um ponto de referência?

O que é o resultado acionável vai ser?

Medição contra alguma base de código de referência só vai lhe dizer que você está algoritmo não é o algoritmo de referência. É uma conclusão precipitada de que você vai ser diferente; geralmente mais lento.

Obviamente, o resultado de medição contra LINPACK será (a) você é diferente e, portanto, (b) você precisa para otimizar.

A medição só é realmente valioso quando feito contra se . Não algum mix instrução hipotética, mas o seu próprio mix de instruções. Medir o seu próprio desempenho. Fazer uma mudança. Veja se o seu desempenho - em comparação com você mesmo -. Ficar melhor ou pior

FLOPS não importa. O que importa é o tempo por unidade de trabalho. Você nunca vai corresponder aos parâmetros de design do seu hardware porque você não está rodando o benchmark que seus projetistas de hardware esperado.

LINPACK não importa. O que importa é a sua base de código e o que você está fazendo mudanças para o desempenho mudança.

questão velho com, se popular, respostas que não são exatamente grande, IMO.

A “FLOP” é uma operação matemática de ponto flutuante. “ALETA” pode significar uma de duas coisas:

  • A simples plural de “FLOP” (ou seja, “a operação X leva 50 flops”)
  • O taxa de fracassos no primeiro sentido (isto é, operações matemáticas de ponto flutuante por segundo)

Quando não é claro a partir do contexto, qual destes é significado é muitas vezes disambiguated escrevendo a primeira como “flops” eo segundo como “FLOP / s”.

flops são chamados para distingui-los de outros tipos de operações de CPU , tais como operações com números inteiros matemática, operações lógicas, operações bit a bit, operações de memória e operações de ramificação, que têm custos diferentes (leitura “assumir diferentes comprimentos de tempo”) que lhes estão associados.

A prática de datas “FLOP contagem” de volta para os primeiros dias de computação científica, quando flops foram, relativamente falando, extremamente caro, levando muitos ciclos de CPU cada. Um co-processador 80387 matemática, por exemplo, levou algo como 300 ciclos para uma única multiplicação. Este foi em um momento antes pipelining e antes que o abismo entre velocidades de clock de CPU e velocidades de memória tinha realmente abriu: operações de memória levou apenas um ciclo ou dois, e ramificação ( “tomada de decisão”) foi igualmente barato. Naquela época, se você pudesse eliminar uma única FLOP em favor de uma dúzia de acessos de memória, você fez um ganho. Se você pudesse eliminar uma única FLOP em favor de uma dezena de filiais, você fez um ganho. Então, no passado, fez sentido para contar flops e não se preocupar muito com referências de memória e ramos, porque flops fortemente dominadas tempo de execução porque eles eram, individualmente, muito caro em relação a outros tipos de operação.

Mais recentemente, a situação se inverteu. Flops tornaram-se muito barato - qualquer Intel moderna núcleo pode executar cerca de dois flops por ciclo (embora divisão permanece relativamente caro) - e acessos de memória e ramos são comparativamente muito mais caro: um cache L1 bateu custos talvez 3 ou 4 ciclos, uma busca de custos principais de memória 150-200. Dada esta inversão, já não é o caso que a eliminação de um FLOP em favor de um acesso à memória irá resultar em um ganho ; na verdade, isso é improvável. Da mesma forma, muitas vezes é mais barato para “apenas faça” um fracasso, mesmo que seja redundante, em vez de decidir se a fazê-lo ou não. Isso é muito bonito o oposto completo da situação há 25 anos.

Infelizmente, a prática de cegos FLOP de contagem como uma métrica absoluta de mérito algorítmica tem persistido bem passado o seu prazo de validade. computação científica moderna é muito mais sobre o gerenciamento de largura de banda de memória - tentando manter as unidades de execução que fazer o flops constantemente alimentado com dados - que se trata de reduzir o número de flops. A referência ao LINPACK (que foi essencialmente obsoleta por LAPACK 20 anos) me leva a suspeitar que seu empregador é, provavelmente, de uma escola muito antiga que não tenha internalizado o fato que a criação de expectativas de desempenho não é apenas uma questão de FLOP contar mais nada. Um solver que faz duas vezes mais flops ainda poderia ser vinte vezes mais rápidas do que outra se tem um padrão de acesso à memória e dados de layout muito mais favorável.

O resultado de tudo isto é que a avaliação de software computacionalmente intensivas desempenho tornou-se muito mais complexa do que costumava ser . O fato de que flops tornaram-se barato é extremamente complicado pela maciça variabilidade dos custos das operações de memória e ramos. Quando se trata de avaliar algoritmos , contagem FLOP simples simplesmente não informa expectativas de desempenho global mais.

Talvez a melhor maneira de pensar sobre as expectativas de desempenho e avaliação é fornecido pelo chamado modelo de teto , que está longe de ser perfeito, mas tem a vantagem de fazer você pensar sobre o trade-off entre flutuante questões pontuais e de largura de banda de memória ao mesmo tempo , proporcionando uma “imagem 2D” mais informativo e perspicaz que permite a comparação das medições de desempenho e expectativas de desempenho.

Vale a pena dar uma olhada.

A FLOPS é, como você disse, uma operação de ponto flutuante por segundo. Como exemplo, se você tomar exatamente um segundo para uma operação (como adicionar, subtrair, multiplicar ou dividir dois valores e retornando o resultado), o seu desempenho é simplesmente um flops. A CPU recente será facilmente atingir várias gigaflops, ou seja, vários bilhões de operações de ponto flutuante por segundo.

Gostaria apenas de tentar torná-lo ir tão rápido quanto possível, e que requer descobrir onde ele está gastando o tempo, especialmente se houver chamadas de funções que poderiam ser evitados.

Eu faço isso pelo simples método de apenas interromper algumas vezes enquanto ele está executando, e vendo o que está fazendo. Aqui estão os tipos de coisas que eu acho:

  • Grande parte do tempo que está em processo de calcular a derivada e / ou Jacobian. Muito desse tempo pode entrar em chamadas de função matemática, como exp(), log() e sqrt(). Muitas vezes, estes são repetidos com argumentos idênticos e podem ser ized-memo. (Aceleração maciça.)

  • A maior parte do tempo é gasto cálculo derivados muitas vezes porque as tolerâncias de integração são mais apertado do que o necessário. (Faster)

  • Se um algoritmo de integração implícita (como DLSODE Gear) está sendo usado porque as equações são pensados ??para ser duro, as chances são de que eles não são, e algo como Runge-Kutta poderia ser usado. (DVERK). (Mais rápido ainda)

  • Possivelmente um algoritmo de matriz expoente pode ser usado se o modelo é linear (DGPADM). Esta é uma grande vitória, tanto para desempenho e precisão, e é imune a rigidez. (Caminho mais rápido)

  • superior a chamada-pilha, pode ser que os mesmos estão a ser realizadas as integrações repetidas vezes com um pouco diferentes parâmetros, de modo a determinar um gradiente para a frente ou de diferenças central da solução no que diz respeito a esses parâmetros. Se as equações diferenciais são eles próprios diferenciável, pode ser possível obter essas gradientes analiticamente, ou aumentando as equações com as equações de sensibilidade. Isto não só é muito mais rápido, mas muito mais precisa, o que pode acelerar as coisas ainda mais acima na pilha.

Você pode olhar para cada nível da pilha como uma oportunidade para encontrar coisas para otimizar, e os aumentos de velocidade será composto. Então, quando você vai para multi-cpu, assumindo que é paralelizável, que deve fornecer seu próprio fator multiplicativo.

Então, de volta para flops. Você poderia tentar maximizar FLOPs / second, mas também pode ser muito mais útil para minimze FLOPs / run, por meio da otimização em todos os níveis da pilha. Em qualquer caso, apenas medição lhes diz quase nada.

O seu empregador é certo.
A única maneira de medir a eficácia de seu programa de Fortran (ou de qualquer outro programa, btw) é testá-lo contra benchmarks padrão, se existirem.

E, sobre flops, que defende "operações de ponto flutuante por segundo" - veja a definição na Wikipedia.

Eu não acho medição FLOPS será muito útil.

O número de fracassos alcançados irá dizer-lhe quão ocupado o seu algoritmo é manter o CPU, mas não vai dizer-lhe quão bem o seu próprio algoritmo está realizando.

Você pode encontrar dois algoritmos diferentes que causam o processador para executar o mesmo número de FLOPS mas fornece-lhe com o resultado desejado na metade do tempo.

Eu acho que você seria melhor fora olhando para um 'nível mais elevado' muito estatística, tais como o número de equações diferenciais resolvido por unidade de tempo (que é, afinal, o objectivo do seu algoritmo).

Por outro lado, medindo o número de fracassos conseguido pode ajudá-lo a melhorar o seu algoritmo como ele vai lhe dizer o quão ocupado você está mantendo o CPU.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top