domingo, 4 de abril de 2010
COMO MODIFICAR ALGO QUE JÁ FOI ESCRITO NA TELA - MOSTRAR PORCENTAGEM DE PROCESSAMENTO...
Basta declarar uso da biblioteca que permite manipular a saída padrão (Standard Output) obter o handle (identificador) da mesma, posicionar o cursor no local que se deseja modificar o que foi escrito, e escrever o que quiser.
Em outras palavras...
PROGRAM MAIN
USE DFLIB !PARA PODER UTILIZAR A FUNÇÃO SLEEP
USE DFWIN !PARA TER ACESSO ÀS FUNÇÕES RELACIONADAS AO CONSOLE
INTEGER :: I, HANDLE1 !UM INTEIRO PARA A PORCENTAGEM,
!OUTRO PARA O IDENTIFICADOR
TYPE(T_COORD) WPOS1 !PARA ARMAZENAR A POSIÇÃO
LOGICAL LSTAT1
!OBTENDO O IDENTIFICADOR DA SAÍDA PADRÃO
HANDLE1 = GETSTDHANDLE(STD_OUTPUT_HANDLE)
! POSIÇÃO ONDE SE VAI ESCREVER
WPOS1.X = 0 ! 0 CARACTERES PARA A ESQUERDA
WPOS1.Y = 0 ! 0 LINHAS PARA BAIXO
DO I=1,100
!POSICIONANDO
LSTAT1 = SETCONSOLECURSORPOSITION(HANDLE1, WPOS1)
!ESCREVENDO
WRITE(*,*) I,'%'
!ESPERANDO
CALL SLEEPQQ(200)
END DO
END PROGRAM MAIN
segunda-feira, 22 de março de 2010
Comparação: MATMUL versus DGEMM (Multiplicação de Matrizes)
Os dois casos explicados a seguir foram feitos para TAM = 1000, ou seja, para matrizes de tamanho 1000 x 1000.
PRIMEIRO CASO
Para o primeiro caso, as matrizes a serem multiplicadas (A*B) são definidas como:
DO i=1,TAM
DO j=1,TAM
A(i,j) = i + j
B(i,j) = i + j
END DO
END DO
SEGUNDO CASO
Para o segundo caso, as matrizes a serem multiplicadas (A*B) são definidas como:
DO i=1,TAM
DO j=1,TAM
A(i,j) = i - j
B(i,j) = i + j
END DO
END DO
RESULTADOS
Os resultados estão resumidos no seguinte gráfico:
Para os dois casos estudados, MATMUL foi cerca de 5 vezes mais lento que DGEMM.
CONCLUSÕES
Caso você tenha acesso à biblioteca IMSL, vale a pena gastar um pouco de tempo substituindo a função MATMUL pela DGEMM em todos os seus programas que utilizem multiplicação de matrizes.
Caso não tenha acesso a esta biblioteca, vale a pena ver se há outra subrotina que você possa utilizar no lugar da MATMUL e fazer uma breve comparação entre elas.
domingo, 21 de março de 2010
Comparação (de velocidade de processamento): mesclando código .FOR + .F90, usando ou não subrotinas (funções)...
Neste post são comparados alguns resultados (de tempo de processamento) para a realização de um conjunto determinado de operações, englobando os casos a seguir. Todos os exemplos foram desenvolvidos utilizando o Compaq Visual Fortran 6.6.
1. F90
O código é todo escrito em Fortran 90. São feitos dois arquivos, MAIN.F90 e FUNC.F90. O programa MAIN chama a função presente em FUNC.F90 um total de NUM_ITE vezes, e repete o procedimento um total de NUM_REPETICOES vezes, obtendo a média do tempo de processamento.
2. F90 + FOR
Semelhante ao caso .F90, sendo que o arquivo MAIN é um .F90, e o arquivo FUNC é um .FOR (formato fixo).
3. F90 Direto
O arquivo FUNC deixa de existir, as operações são inseridas no arquivo MAIN diretamente. O código é todo escrito em F90.
4. FOR Direto
Semelhante ao F90 Direto, mas o código é todo escrito em formato fixo (.FOR).
5. F90 mesclado
Todo o código do arquivo FUNC é inserido após o fim do programa MAIN, de forma que se trabalha com uma subrotina (função) à parte, mas tanto o programa quanto a função ficam presentes no mesmo arquivo. Todo o código é escrito em formato livre (.F90).
6. FOR mesclado
Semelhante ao F90 mesclado, mas o código é escrito em formato fixo.
QUAIS SÃO AS OPERAÇÕES EFETUADAS?
Foram executados três exemplos com diferentes conjuntos de operações, para todos os casos NUM_REPETICOES = 3 (para efetuar a média de tempo de processamento).
PRIMEIRO CONJUNTO DE OPERAÇÕES
Y = X**2
Y = Y + 0.02D0
NUM_ITE = 1E9
SEGUNDO CONJUNTO DE OPERAÇÕES
Y = X**2
Y = Y + 0.02D0
Y = SQRT(Y)
Y = Y/2.25D0
NUM_ITE = 5E8
TERCEIRO CONJUNTO DE OPERAÇÕES
Y = X**2.2D0
Y = Y + 0.0225D0
Y = SQRT(Y)
Y = SIN(Y)
Y = Y/2.25673D0
Y = COS(Y)
NUM_ITE = 5E7
QUAIS FORAM OS RESULTADOS?
O tempo de processamento para cada caso é mostrado na figura abaixo.

CONCLUSÕES
Para os casos estudados:
1 - Mesclar códigos escritos em .FOR com códigos em .F90 não leva a grandes diferenças de custo computacional.
2 - Utilizar subrotinas (funções) em diferentes arquivos ou mescladas num mesmo arquivo não leva a grandes diferenças também.
3 - Efetuar as operações diretamente no código principal é mais rápido do que efetuar as operações em subrotinas (funções) à parte. No entanto, à medida que a complexidade das operações aumenta, o custo de chamada da função perde importância.
Portanto, para grandes problemas (com operações complexas) a clareza de código obtida utilizando subrotinas supera de longe o acréscimo de custo computacional.
4 - Para problemas mais complexos (conjunto de operações 3) todos os seis casos apresentaram praticamente o mesmo custo computacional.
-------------------- x ----------------------- x -----------------------
domingo, 13 de dezembro de 2009
MATLAB versus FORTRAN - 1 - somatório simples
No intuito de medir o tempo nos dois ambientes sem que haja muita diferença no método de medição, optou-se por utilizar as funções tic e toc, no MATLAB, e a função TIMEF() do FORTRAN (biblioteca DFPORT). A descrição destas funções é a seguinte:

O primeiro exemplo é um somatório simples, para i variando de 1 a 1 bilhão, conforme o código abaixo (em MATLAB):
j=0;
tic
for i=1:1000000000
j=j+1;
end
toc
O número de linhas do código fonte foi de 6 linhas para o MATLAB contra 10 linhas do FORTRAN (sem contar cabeçalho e finalização da função).
O tempo médio de execução para 10 repetições é mostrado a seguir:

Verificou-se que, para este exemplo, o MATLAB foi quase duas vezes mais lento que o FORTRAN.
segunda-feira, 6 de julho de 2009
Comparação - ACESSANDO MATRIZES... (RANK 2 ARRAYS)
Por exemplo, com uma matriz de três dimensões se teria:
!LOOP mais rápido
DO K=1,N3
DO J=1,N2
DO I=1,N1
A(I,J,K) = ...
END DO
END DO
END DO
Qualquer alteração da ordem desses LOOPs resulta num código mais lento.
Tomando-se o caso de duas dimensões apenas, qual seria a diferença de velocidade do loop mais rápido para o mais lento?
Na busca por respostas para essa pergunta, foi desenvolvido um pequeno projeto no Compaq Visual Fortran 6.6 ( 288Kb). Para uma matriz A de dimensão NxN, onde N=5000, foram rodados 20 vezes os códigos que permitiram colocar o valor de cada elemento da matriz como sendo
A(I,J) = A(I,J) + I**2 + J**2,
acessando linha por linha (mais lento) e coluna por coluna (mais rápido).
O tempo médio e o tempo médio relativo foram obtidos para comparação.
Os resultados foram os seguintes:

Ou seja, para este caso específico a diferença já mostrou ser muito grande. O acesso coluna por coluna chega a ser quase 5 vezes mais rápido que o acesso linha por linha. Um bom motivo para varrer seus códigos-fonte e excluir os loops coluna por coluna deles sempre que possível.
sexta-feira, 19 de junho de 2009
CONCLUSÃO da comparação - LOOPs (DO x DO WHILE x DO "INFINITO")
ALGUMAS CONCLUSÕES...
O tipo de loop mais rápido varia com os códigos executados no loop e depende também do compilador. De qualquer forma, nos casos em que o DO WHILE foi melhor que os outros, os outros ficaram muito próximos. E no geral o loop do tipo DO foi o que se saiu melhor, pois ele é o mais rápido em alguns casos, e nas vezes que não é ainda assim fica bem próximo do melhor.
Esse loop seria definido genericamente por:
CASO 1 : LOOP DO
DO I=1,N
.
.
.
END DO
E seria "o mais rápido" dos três casos verificados.
quinta-feira, 18 de junho de 2009
Comparação - LOOPs (DO x DO WHILE x DO "INFINITO")
Os Loops em estudo são definidos genericamente da seguinte forma, onde N é um inteiro:
CASO 1 : LOOP DO
DO I=1,N
.
.
.
END DO
CASO 2 : LOOP DO WHILE
DO WHILE (I<=N) .
.
.
I = I + 1
END DO
CASO 3 : LOOP DO "INFINITO"
LOOP1 : DO
.
.
.
I = I + 1
IF (I==N) EXIT LOOP1
END DO LOOP1
Os resultados INICIAIS encontrados, apresentados na tabela abaixo, confirmaram que o DO WHILE é mais lento que os outros loops acima mostrados.

A tabela mostra os valores obtidos para uma função qualquer, comprovando que a mesma coisa estava sendo calculada nos três casos. Foram feitos dois loops, um dentro do outro, com N=25000, ou seja, 625 milhões de cálculos da função (X = X + (-1**J)*X/N, onde J varia em um dos loops). Tomou-se um tempo relativo ao tempo do Loop Do "Infinito".
Constatou-se PARA ESTE N ESPECÍFICO que o caso 2 demora cerca de 2% a mais de tempo do que a referência, enquanto que o caso 3 leva cerca de 0,7%.
O estudo foi feito utilizando o Compaq Visual Fortran 6.6, e o projeto completo está disponível para download aqui (294Kb).
ATUALIZAÇÃO:
Este mesmo post gerou discussões e mais discussões na comunidade supracitada. Algumas conclusões podem ser vistas AQUI.
quinta-feira, 11 de junho de 2009
Otimização de códigos FORTRAN
Detalhes muito interessantes que encontrei no site da Pós Graduação em Engenharia Civil da UFRGS. Vale a pena dar uma lida:
http://www.cpgec.ufrgs.br/masuero/otimizacao/otimizacao.htm .
sexta-feira, 5 de junho de 2009
Como utilizar a Derivação automática? - EXEMPLO COMPLETO
São três arquivos diferentes denominados no meu projeto como sendo: MAIN.F90, que contem o código PROGRAM TEST dado abaixo, FUNCOES.F90, que contem o módulo FUNCOES, também dado abaixo, e DERIV_CLASS.F90, o módulo de derivação cujo link está disponível no post Derivação Automática.
----------------- CÓDIGO PARA O MAIN.F90 ----------------------
PROGRAM TEST
USE DERIV_CLASS ! torna o módulo de derivação disponível
USE FUNCOES
INTEGER, PARAMETER :: TAM_X=3 !tamanho do vetor x
REAL*8 :: F_, X_(TAM_X), DF(TAM_X) !variáveis p/ armazenar valores de f, x e derivada
REAL*8 :: DDF(TAM_X * (TAM_X + 1) / 2) !variável p/ armazenar valor da 2a derivada
TYPE (FUNC) :: X(TAM_X), F !Para usar o módulo é preciso utilizar estes tipos
!Valores de X para os quais se deseja calcular a derivada
X_(1) = 1.0D0
X_(2) = 1.3D0
X_(3) = 1.8D0
! Zerando o valor da derivada até então
DF = 0.0D0
CALL DERIVATIVE(2) !declara a ordem da derivada - 2 indica 1a e 2a derivadas
! DECLARAR AS VARIÁVEIS INDEPENDENTES(X) E SEUS VALORES (X_)
CALL INDEPENDENT(1, X(1), X_(1)) !primeira variável independente
CALL INDEPENDENT(2, X(2), X_(2)) !segunda variável independente
CALL INDEPENDENT(3, X(3), X_(3)) !terceira variável independente
F = F1(X,TAM_X) !definindo q a função é calculada pela função f1, presente no módulo funcoes
!Extraindo valores das derivadas e mostrando os mesmo na tela.
CALL EXTRACT(F, DF, DDF)
WRITE(*, *) 'DF',DF
WRITE(*, *) 'DDF',DDF
END PROGRAM TEST
----------------- CÓDIGO PARA O MÓDULO FUNCOES ----------------------
MODULE FUNCOES
USE DERIV_CLASS
CONTAINS
FUNCTION F1(X,TAM_X) RESULT(Y)
INTEGER :: TAM_X
TYPE (FUNC) :: X(TAM_X), Y
!AQUI PODE SER ESCRITA QUALQUER FUNÇÃO DE X(TAM_X)
Y = 2*X(1)**2 + X(2)**3 + COS(X(3))
END FUNCTION
END MODULE FUNCOES
-------------------------MUITO IMPORTANTE -----------------------------------
----------------- ALTERAÇÃO NO MÓDULO DERIV_CLASS ----------------------
MODULE deriv_class IMPLICIT NONE
PRIVATE
INTEGER, PARAMETER :: n = 3 ! <<< AQUI precisa-se colocar o valor de tam_x
------------------------------------------------------------------------------------
Como o código é aberto, podem ser feitas as alterações que o usuário achar necessário. Por exemplo, pode-se colocar o parâmetro n do módulo Deriv_class em função do TAM_X já declarado anteriormente.
Até mais.
quarta-feira, 3 de junho de 2009
Derivação automática
A solução que mais me chamou a atenção foi a da Derivação automática. Pelas razões encontradas na tabela das notas de aula:
e pela existência de um código fonte disponível para FORTRAN que efetua tal operação.
Trata-se do AUTO_DERIV, desenvolvido por S. Stamatiadis, R. Prosmiti e S. C. Farantos, da "University of Crete" (Grécia) e do "Institute of Electronic Structure and Laser Foundation for Research and Technology - Hellas".
O código permite calcular a primeira e a segunda derivadas parciais de qualquer função contínua com muitas variáveis independentes. Além disso, a função a ser derivada pode depender de outras várias subrotinas ou funções escritas em linguagem Fortran 90 ou 77.
Um artigo completo sobre o código fonte está disponível.
O código fonte (+ exemplos) pode ser baixado direto por este link retirado deste site, ou pelo site http://cpc.cs.qub.ac.uk/summaries/ADLS, que parece estar fora do ar por algum tempo.
Qualquer dúvida sobre a utilização do programa pode ser colocada em comentários aqui ou na comunidade do orkut: Fortran 90/95/2003 BR.
Até mais.
sexta-feira, 29 de maio de 2009
PARSER - avaliador de Expressões - f(x) = sin(x) + x**2 ... automaticamente.
publicado no Science & Engineering Journal de 2005.