Pergunta

Eu tenho esse código fortran 'simplificado'

real B(100, 200) 
real A(100,200)

... initialize B array code.

do I = 1, 100
  do J = 1, 200
    A(J,I) = B(J,I)
  end do
end do

Um dos gurus de programação me avisado, que acessa fortran dados de forma eficiente, a fim de coluna, enquanto c acessa os dados de forma eficiente, a fim de linha. Ele sugeriu que eu dê uma boa olhada no código, e estar preparado para interruptor laços em torno de manter a velocidade do programa de idade.

Sendo o programador preguiçoso que sou, e reconhecendo os dias de esforço envolvido, e os erros que eu sou propensos a fazer, eu comecei a pensar se poderia uma técnica #define que me deixou converter este código de segurança, e facilmente.

Você tem alguma sugestão?

Foi útil?

Solução

Em C, multi-dimensional arrays de trabalho como este:

#define array_length(a) (sizeof(a)/sizeof((a)[0]))
float a[100][200];
a[x][y] == ((float *)a)[array_length(a[0])*x + y];

Em outras palavras, eles são matrizes realmente planas e [][] é apenas açúcar sintático.

Suponha que você faça o seguinte:

#define at(a, i, j) ((typeof(**(a)) *)a)[(i) + array_length((a)[0])*(j)]
float a[100][200];
float b[100][200];
for (i = 0; i < 100; i++)
    for (j = 0; j < 200; j++)
        at(a, j, i) = at(b, j, i);

Você está andando sequencialmente através da memória, e fingindo que a e b estão realmente dispostas em ordem de coluna-major. É uma espécie de horrível em que a[x][y] != at(a, x, y) != a[y][x], mas contanto que você lembre-se que ele está enganado como este, você vai ficar bem.

Editar

O homem, eu me sinto idiota. A intenção desta definição é fazer at(a, x, y) == at[y][x], e ele faz. Assim, o muito mais simples e mais fácil de entender

#define at(a, i, j) (a)[j][i]

seria melhor que o que eu sugeri acima.

Outras dicas

Você tem certeza suas caras Fortran fez as coisas direito?

O trecho de código que você originalmente publicado já está acessando os arrays em ordem da maior linha (que é 'ineficiente' para Fortran, 'eficiente' para C).

Como ilustrado pelo trecho de código e, como mencionado na sua pergunta, recebendo este 'correta' pode ser propenso a erros. A preocupação sobre como obter o código FORTRAN portado para C primeiro sem se preocupar com detalhes como este. Quando a porta está trabalhando -., Em seguida, você pode se preocupar em mudar coluna ordem acessos a linha de ordem acessos (mesmo se ele realmente importa após a porta está funcionando)

Um dos meus primeiros trabalhos de programação fora da faculdade era fixar um aplicativo de longa duração C que tinha sido portado do Fortran. As matrizes foram muito maiores do que a sua e que estava tomando algo em torno de 27 horas por corrida. Depois de corrigi-lo, eles correram em cerca de 2,5 horas ... muito doce!

(OK, ele realmente não foi atribuído, mas eu estava curioso e encontrou um grande problema com o seu código. Alguns dos veteranos não gostava muito de mim, apesar de essa correção.)

Parece que o mesmo problema é encontrado aqui.

real B(100, 200) 
real A(100,200)

... initialize B array code.

do I = 1, 100
  do J = 1, 200
    A(I,J) = B(I,J)
  end do
end do

Seu looping (para ser bom FORTRAN) seria:

real B(100, 200) 
real A(100,200)

... initialize B array code.

do J = 1, 200
  do I = 1, 100
    A(I,J) = B(I,J)
  end do
end do

Caso contrário, você está marchando pelas matrizes em linha principal, que poderiam ser altamente ineficiente.

Pelo menos eu acredito que isso é como seria em Fortran - tem sido um longo tempo

.

Saw lo atualizado o código ...

Agora, você iria querer trocar as variáveis ??de controle de loop para que você iterate nas linhas e, em seguida, dentro dessa iterate nas colunas se você estiver convertendo a C.

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