Quando eu estava estudando na universidade, ouvi muitas vezes a idéia de que os compiladores Fortran produziam código mais rápido que os compiladores C para um programa equivalente.
O principal raciocínio foi o seguinte: um compilador Fortran emite em média 1,1 instruções do processador por linha de código, enquanto um compilador C emite em média 1,6 instruções do processador por linha de código - não me lembro dos números exatos, mas o A idéia era que os compiladores C emitissem visivelmente mais código de máquina e, portanto, produzissem programas mais lentos.
Quão válida é essa comparação? Podemos dizer que os compiladores Fortran produzem programas mais rápidos que os compiladores C ou vice-versa e por que essa diferença existe?
c
comparison
compiler
fortran
dente afiado
fonte
fonte
Respostas:
O IIRC, um dos principais motivos pelos quais o Fortran é mais rápido, é a ausência de alias de ponteiro , para que eles possam usar otimizações que os compiladores C não podem usar:
Mas eu concordo com outras pessoas aqui: comparar o número médio de instruções do assembler geradas para uma linha de código é um absurdo completo. Por exemplo, um núcleo x86 moderno pode executar duas instruções em paralelo se não acessar os mesmos registros. Assim, você pode (em teoria) obter um aumento de desempenho de 100% para o mesmo conjunto de instruções apenas reordenando-as . Bons compiladores também geralmente geram mais instruções de montagem para obter um código mais rápido (pense em desenrolar o loop, embutir). O número total de instruções do assembler diz muito pouco sobre o desempenho de um pedaço de código.
fonte
restrict
palavra-chave C permite que o autor de uma função especifique que um ponteiro não possui aliases. Isso é suficiente para resolver a diferença ou há mais?Comparação completamente inválida.
Primeiro, como @ Péter Török salienta, você deve primeiro comparar o número de linhas em programas equivalentes do Fortran e C para que isso seja uma comparação válida no número de linhas produzidas.
Segundo, menos linhas de código nem sempre são iguais a programas mais rápidos . Nem todas as instruções da máquina levam o mesmo número de ciclos para serem executadas , mas você também tem outros problemas, como acesso à memória , cache , etc.
Além disso, execuções longas de código podem ser mais rápidas, pois resultam em um número menor de linhas de execução (ou seja, Contagem de Linhas! = Contagem de Linhas Executadas ).
fonte
Dan está correto, programas mais longos não significam programas mais lentos. Depende muito do que eles estão fazendo.
Não sou especialista em Fortran, sei um pouco. Comparando-os, eu pensaria que C bem escrito teria um desempenho muito melhor com estruturas e funcionalidade de dados mais complexas que o Fortran. Alguém (por favor) me corrija se eu estiver errado aqui, mas acho que o Fortran está um pouco em um 'nível mais baixo' do que o C.
Outra coisa, à primeira vista, pensei que você estivesse perguntando se os compiladores são mais rápidos. Na verdade, acho que o Fortran geralmente compila mais rapidamente para quantidades semelhantes de código, mas o programa resultante e como ele é executado seria uma história diferente. É apenas mais simples de analisar.
fonte
Eu acho que parte disso é que os compiladores FORTRAN são projetados para fazer alguns tipos de matemática muito rapidamente. É por isso que as pessoas usam o FORTRAN para fazer cálculos o mais rápido possível
fonte
A afirmação pode ter sido verdadeira nos velhos tempos (por volta dos anos 70), quando C estava em sua infância, e o Fortran era apoiado por todos os principais fabricantes e era altamente otimizado. Os primeiros Fortrans eram baseados na arquitetura da IBM, coisas tão simples como a aritmética se certamente teriam sido uma instrução por instrução de montagem. Isso é verdade em máquinas mais antigas, como Data General e Prime, que tinham saltos de 3 vias. Isso não funciona em conjuntos de instruções modernos que não possuem um salto de três direções.
Linhas de código não são iguais a instruções de código. As versões anteriores do Fortran permitiam apenas uma instrução por linha. Versões posteriores do Fortran podem receber várias instruções por linha. C pode ter várias instruções por linha. Nos compiladores de produção mais rápidos, como o IVF da Intel (anteriormente CVF, MS Powerstation) e o C da Intel, realmente não há diferença entre os dois. Esses compiladores são altamente otimizados.
fonte
O FORTRAN à moda antiga exigia que um programador que quisesse disponibilizar parte de uma matriz para uma função passasse uma referência a toda a matriz, juntamente com um ou mais valores inteiros, especificando o índice inicial e o índice final ou o número de itens . C torna possível simplificar isso passando um ponteiro para o início da parte de interesse junto com o número de elementos. Em termos diretos, isso tornaria as coisas mais rápidas (passando duas coisas em vez de três). Indiretamente, no entanto, isso pode resultar em lentidão, limitando os tipos de otimização que um compilador pode executar.
Considere a função:
se um compilador soubesse que cada um dos ponteiros identificaria o início de uma matriz, ele poderia gerar código que atuaria sobre os elementos da matriz em paralelo ou em qualquer ordem, pois para qualquer x! = y, operações em dest [x ] não afetará src1 [y] nem src2 [y]. Por exemplo, em alguns sistemas, um compilador pode se beneficiar da geração de código equivalente a:
Observe que toda operação que carrega ou calcula um valor tem pelo menos mais uma operação entre ele e a próxima operação que usa esse valor. Alguns processadores podem se sobrepor ao processamento de diferentes operações quando essas condições forem atendidas, melhorando assim o desempenho. Observe, no entanto, que como um compilador C não tem como saber que o código não passará ponteiros para regiões parcialmente sobrepostas de uma matriz comum, um compilador C não pode fazer a transformação acima. Os compiladores FORTRAN que receberam código equivalente, no entanto, puderam e fizeram essa transformação.
Enquanto um programador C poderia tentar obter desempenho comparável escrevendo explicitamente o código que desenrolava o loop e sobrepunha as operações de passagens adjacentes, esse código poderia facilmente prejudicar o desempenho se usasse tantas variáveis automáticas que um compilador precisava "derramar" para memória. O otimizador de um compilador FORTRAN provavelmente saberia mais do que um programador sobre quais formas de intercalação produziriam um desempenho ideal em um determinado cenário, e é melhor deixar essas decisões para esses compiladores. Enquanto o C99 tentava melhorar um pouco a situação de C adicionando um
restrict
qualificador, isso só poderia ser usado aqui se houvessedest[]
uma matriz separada de ambossrc1[]
esrc2[]
, ou se o programador adicionasse versões separadas do loop para lidar com os casos em que tudodest
estava separado.src1
esrc2
, ondesrc1[]
edest
eram iguais esrc2
eram disjuntos, ondesrc2[]
edest[]
eram iguais esrc1
eram disjuntos, e onde todas as três matrizes eram iguais. O FORTRAN, por outro lado, poderia lidar com todos os quatro casos sem dificuldade usando o mesmo código-fonte e o mesmo código de máquina.fonte