Fortran90

Transcription

Fortran90
Fortran90
in Kürze
Dieter an Mey,
Rechenzentrum der RWTH Aachen
14. März 2001
[email protected]
http://www.rz.rwth-aachen.de [/hpc]
Programmiersprachen im Hochleistungsrechnen
Verbreitung (persönliche Einschätzung)
FORTRAN77
Fortran90/95
C
C++
Java
Programmiersprachen
Derzeit im Hochleistungsrechnen hier genutzte Sprachen (Schätzung)
Fortran77 (ext) ca. 80-90%
C ca. 10-20 % (Tendenz steigend)
Fortran90 selten
C++ selten
Meine Empfehlung: Sehen Sie sich Fortran90 an !
Fortran90 ist zu Fortran77 aufwärts kompatibel
Fortran90 schließt die Möglichkeiten von C weitgehend ein
Fortran90 kann auch einiges von C++
Es ist für techn.-wiss. Aufgabenstellungen häufig
die geeignetere Sprache
Ausgereifte Compiler stehen auf allen Plattformen zur Verfügung
(Es gibt auch eine p.d. Version für Linux, basierend auf g77)
Evtl. ist die Kombination von Fortran90 und C(++) zu erwägen.
Fortran77
wesentliche Charakteristika
Feldverarbeitung ohne Zeiger (Pointer)
COMMON-Blöcke
Call by Reference
Kein Überlappen von beim Aufruf übergebenen Feldern Seiteneffekte
Nicht vergessen!
Felder werden in Fortran spaltenweise abgespeichert !
(und nicht zeilenweise wie z.B. in C)
Fortran77
Feldverarbeitung, Call by Reference
PROGRAM MAIN
IMPLICIT REAL (A-H,O-Z)
IMPLICIT INTEGER (I-N)
PARAMETER (LD1=11,LD2=12,LD3=13)
DIMENSION A(LD1,LD2,LD3)
READ (*,*) N1, N2, N3
CALL SUB ( A, LD1, LD2, N1, N2, N3 )
...
SUBROUTINE ( A, LD1, LD2, N1, N2, N3 )
REAL A(LD1,LD2,*)
DO I1=1,N1
DO I2=1,N2
DO I3=1,N3
A(I1,I2,I3) = ...
END DO
END DO
END DO
...
Fortran77
COMMON-Blöcke
PROGRAM MAIN
PARAMETER (LD1=11,LD2=12,LD3=13)
COMMON / NAME / A(LD1,LD2,LD3)
READ (*,*) N1, N2, N3
CALL SUB ( N1, N2, N3 )
...
SUBROUTINE ( N1, N2, N3 )
PARAMETER (LD1=11,LD2=12,LD3=13)
COMMON / NAME / A(LD1,LD2,LD3)
DO I1=1,N1
DO I2=1,N2
DO I3=1,N3
A(I1,I2,I3) = ...
END DO
END DO
END DO
...
Fortran77
COMMON-Blöcke
PROGRAM MAIN
INCLUDE ´defs.inc`
READ (*,*) N1, N2, N3
CALL SUB ( N1, N2, N3 )
...
C defs.inc
PARAMETER (LD1=11,LD2=12,LD3=13)
COMMON / NAME / A(LD1,LD2,LD3)
SUBROUTINE ( N1, N2, N3 )
INCLUDE ´defs.inc`
DO I1=1,N1
DO I2=1,N2
DO I3=1,N3
A(I1,I2,I3) = ...
END DO
END DO
END DO
...
Fortran77
ACHTUNG! Überlappende Felder
PROGRAM MAIN
PARAMETER (MAX=1000000)
COMMON / NAME / WORK(MAX)
READ (*,*) N1, N2, N3
CALL SUB ( N1,N2,N3, WORK(1),WORK(1+N1),WORK(1+N1+N2) )
...
SUBROUTINE SUB ( N1, N2, N3, A, B, C )
REAL A(*), B(*), C(*)
DO I=1,MIN( N1, N2, N3 ) ! ACHTUNG weiter darf I nicht laufen
A(I) = B(I) + C(I)
END DO
...
Fortran77
ACHTUNG! Seiteneffekt
PROGRAM MAIN
CALL SUB ( 1 )
WRITE (*,*) 1
STOP
END
Was wird ausgegeben ?
SUBROUTINE ( IEINS)
IEINS=2
SUN f77:
POSSIBLE ATTEMPT TO MODIFY CONSTANT
RETURN
END
Segmentation Fault(coredump)
SUN frt:
2
SGI f77/f90: 1
VPP frt:
2
HP f90:
1
LINUX g77: Memory fault(coredump)
LINUX pgf77:1
LINUX pgf90:2
2
Fortran90
Ziele
Einbringen von moderenen Sprachkonstrukten in Fortran77
dynamische Speicherverwaltung, Strukturen, Felder, Rekursionen,
Definition von eigenen Typen, Überladen von Operatoren
Standardisierung der zahlreichen proprietären
Spracherweiterungen von Fortran77
Erhöhung der Programmsicherheit
Module, interne Prozeduren, Schnittstellen (interfaces)
Kompatibilität zu Fortran77
Komfort
Fortran90
Neue Eigenschaften
Feldverarbeitung
Dynamische Speicherverwaltung, automatische Felder
Module
Prozeduren mit optionalen und Schlüsselwortparametern
interne Prozeduren
rekursive Prozeduren
Zeiger
freies Quellformat
Vereinbarungen, IMPLICIT NONE
abgeleitete Typen
Operatorüberladung
CASE-Anweisung
EXIT und CYLCE
zahlreiche neue Intrinsic-Funktionen
neue IO-Möglichkeiten
Fortran90
Obsolete Eigenschaften - Empfehlungen
Arithmetisches IF
DO-Schleifenparameter mit reellem Datentyp
DO-Schleifenenden, die kein separates CONTINUE oder END DO besitzen
ASSIGN und assigned GOTO-Anweisungen
Sprung auf END IF von außerhalb des IF-Blockes
Alternative RETURN-Anweisungen
H- Formatbeschreiber
Anstelle von INCLUDE sollten Module verwendet werden
IMPLICIT NONE verwenden
Anstelle von COMMON, BLOCK DATE und EQUIVALENCE
sollten Module und dynamische Speicherverwaltung genutzt werden
Aber: in OpenMP V1.x werden nur COMMON-Blöcke unterstützt,
seit 10/2000 mit V2 auch Modele
Fortran90
Programmzeilen
Freies Format
max. 132 Zeichen je Zeile
Mehrere Befehle in einer Zeile erlaubt mit Semikolon (;) als Trennzeichen
Variablenamen bis 31 Zeichen inkl. Underline (_)
Kommentare hinter dem Ausrufezeichen (!)
Keine überflüssigen Blanks mehr in Schlüsselworten
Folgezeilen durch Undzeichen (&) am Ende der vorangehenden Zeile,
die Folgezeile darf als erstes nichtleeres Zeichen ebenfalls damit (&)
beginnen.
Tipp
Folgezeilen, die sowohl der Fortran77 als auch der Fortran90 Konvention
folgen sollten je ein Undzeichen (&) am Zeilenende in Spalte 73 der
vorangehenden Zeile und ein Undzeichen in der Spalte 6 der Folgezeile
haben.
Fortran90
Logische Ausdrücke
Logische Ausdrücke
Die Zeichen
<, >, <=, >=, ==, /=
sind ebenso wie
.LT., .GT., .LE., .GE., .EQ., .NE.
zu verwenden.
Fortran90
Vereinbarungen
Vereinbarungen
IMPLICIT NONE
REAL, DIMENSION(3), PARAMETER,Attribut-Liste :: a = ( /0.0,0.0,0.0/)
Attribute:
DIMENSION(extends)
PARAMETER
PUBLIC
PRIVATE
POINTER
TARGET
ALLOCATABLE
INTENT(inout)
OPTIONAL
SAVE
EXTERNAL
INTRINSIC
Fortran90
Verschiedenes
DATA i /B‘01010101010101010101010101010101‘/
DATA i /O‘01234567‘/
DATA i /Z‘ABCDEF‘/
a = ´´
a(:5) = a(3:7)
! binär
! oktal
! hexadezimal
! leere Zeichenkette
! Zuweisung von einander überlappenden Zeichenketten
Fortran90
Kontrollstrukturen - Bedingung
Bedingung dürfen einen Namen erhalten
name:
IF ( log.exp. ) THEN
block
ELSE IF ( log.exp. ) THEN name
block
ELSE name
block
END IF name
Fortran90
Kontrollstrukturen - Fallunterscheidung
Fallunterscheidung
name:
SELECT CASE (3*i-j)
CASE(0) name
...
CASE(2,4:7) name
...
CASE DEFAULT
...
END SELECT name
Fortran90
Kontrollstrukturen - Zählschleife
Zählschleifen
DO ...
END DO
! Endlosschleife
! Hoffentlich gibt es eine Abbruchbedingung!
DO WHILE ( log. exp.)
...
END DO
Den Schleifen dürfen Namen gegeben werden
name:
DO i = ilow, ihigh, istep
...
END DO name
Beenden des aktuellen Schleifendurchlaufes
CYCLE name
Beenden der akutellen Schleifenausführung
EXIT name
Fortran90
Programmeinheiten
Programmeinheiten sind Hauptprogramm und externe Prozeduren, wie in Fortran77
Prozeduren sind Unterprogramme oder Funktionen
Externe Prozeduren sind abgschlossene Programmeinheiten und können von außen
aufgerufen werden (und müssen nicht alle in Fortran programmiert sein)
NEU
Module
Ein Modul enthält Vereinbarungen, die in anderen Programmeinheiten genutzt
werden können (USE-Anweisung, Ersatz für COMMON-Blöcke)
Modulprozeduren
Ein Unterprogramm, daß in einem Modul vereinbart ist, heißt Modulprozedur
interne Prozeduren
Ein Unterprogramm, daß in einem Hauptprogramm, einer externen Prozedur oder
einer Modulprozedur vereinbart ist heißt interne Prozedur.
Interne Prozeduren können nicht geschachtelt werden.
Sie stehen am Ende einer Programmeinheit nach einer CONTAINS-Anweisung
Fortran90
Programmeinheiten - Beispiel
SUBROUTINE sub ( n, x, y, z, sum )
IMPLICIT NONE
INTEGER :: n
REAL, DIMENSION(100) :: x, y, z, sum
sum = add ( a, b, c )
RETURN
CONTAINS
FUNCTION add ( a, b, c ) RESULT ( sum )
IMPLICIT NONE
REAL, INTENT(IN) :: a, b, c
REAL :: sum
sum = a + b + c
END FUNCTION add
END SUBROUTINE sub
Fortran90
Schnittstellenbeschreibungen
Schnittstellenbeschreibungen legen die Einzelheiten der Prozedurargumente fest.
(vgl. Header-Dateien in C, im Unterschied dazu müssen sie aber compiliert werden.)
Zu jedem Aufrufparameter kann die Nutzungsart festgelegt und damit überprüft werden.
INTERFACE
SUBROUTINE sub ( n, x, y, z, sum )
INTEGER :: n
REAL, DIMENSION(100), INTENT(IN) :: x, y, z
REAL, DIMENSION(100), INTENT(OUT) :: sum
END SUBROUTINE sub
END INTERFACE
Fortran90
Aufrufparameter
Aufruf von Programmeinheiten mit Postions- oder Schlüsselwortparametern,
Verwendung von optionalen Parametern
CALL solve ( a, b, n )
CALL solve ( n=i, a=x )
SUBROUTINE solve ( a, b, n )
INTEGER, INTENT(IN) :: n
REAL, INTENT(INOUT) :: a
REAL, OPTIONAL, INTENT(IN) :: b
Fortran90
Rekursive Prozeduren
Rekursive Funktionen müssen das Ergebnis über eine explizit mit der RESULTKlausel vereinbarte Variable zurückgeben
RECURSIVE FUNCTION fact(n) RESULT(res)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n
INTEGER :: res
IF ( n == 1 ) THEN
res = 1
ELSE
res = n * fact(n-1)
ENDIF
END FUNCTION fact
Achtung: Wenn möglich, aus Performance-Gründen rekursive Funktionen
vermeiden.
Fortran90
Feldverarbeitung (1)
Rang (rank) eines Feldes(array): Anzahl der Dimensionen
Ausdehnung (extend) einer Dimension eines Feldes:
Anzahl der Elemente dieser Dim.
Form (shape) eines Feldes: Vektor aller Ausdehnungen
Größe (size) eines Feldes: Gesamtzahl aller Elemente
Konforme (conformable) Felder haben dieselbe Form (shape) und können
miteinander verknüpft werden
Felder sind immer konform zu einem Skalar, dieser wird in Ausdrücken
passend erweitert (broadcast)
Fortran90
Feldverarbeitung (2)
Beispiele
REAL,DIMENSION(5,5) :: ra,rb,rc
INTEGER :: id,i,j
! äquivalent
ra = rb + rc * id
! SHAPE(/5,5/) and scalar
ra(:,:) = rb(:,:) + rc(:,:) * id(:,:) ! SHAPE(/5,5/) and scalar
! äquivalent
ra(3:5,3:4) = rb(1::2,3:5:2) + rc(1:3,1:2)
! SHAPE(/3,2/)
DO j=1,2
DO i=1,3;
ra(i+2,j+2) = rb(2*i-1,2*j+1) + rc(i,j)
END DO
END DO
ra(:,1) = rb(:,1) + rb(:,2) + rc(:,3)
! SHAPE(/5/)
Fortran90
Feldverarbeitung - Bedingungen
WHERE ... ELSEWHERE ... END WHERE
REAL, DIMENSION(100) :: x, y, z
LOGICAL, DIMENSION(100) :: l
...
WHERE ( z >= 1.0e-10 )
x = y / z
ELSEWHERE
x = 0.0e0
END WHERE
...
l = z >= 1.0e-10
x = 0.0e0
WHERE ( l )
x = y/z
END WHERE
Fortran90
Feldverarbeitung - Rekursionen
Vorsicht bei Rekursionen!
(ein Schleifendurchlauf benötigt die Ergebnisse eines vorherigen)
PROGRAM recursion
INTEGER, PARAMETER :: n = 5
INTEGER, DIMENSION(n) :: a
INTEGER :: i
! rekursive Berechnung von a(i) = a(1)+a(2)+...+a(i)
DO i=2,n
a(i) = a(i-1) + a(i)
END DO
! Berechnung von a(i) = a(i) + a(i-1); keine Rekursion
a(2:n) = a(1:n-1) + a(2:n)
! Fortran 90 Lösung (Performance ??!!) :
a(2:n) = (/ (SUM(a(1:i)),i=2,n) /)
END PROGRAM recursion
Fortran90
Dynamische Speicherverwaltung (1)
Dynamische Felder
REAL, DIMENSION (:,:), ALLOCATABLE :: ra
REAL :: xsum
INTEGER :: n, m, status, iseed
READ (*,*) n, m
! read Input matrix size
ALLOCATE (ra(n,m), STAT = status)
IF (status > 0) STOP 'Fail to allocate memory for allocatable array‘
iseed = 1
CALL RANDOM_SEED (PUT=iseed)
CALL RANDOM_NUMBER (ra)
CALL rsum ( ra, xsum )
xsum = SUM( ra )
DEALLOCATE (ra)
Fortran90
Dynamische Speicherverwaltung (2)
Fortsetzung
SUBROUTINE rsum ( ra, xsum )
REAL, DIMENSION (:,:) :: ra
REAL :: xsum
INTEGER :: n, m, status, iseed
xsum = 0.0d0
DO i = 1, SIZE ( ra, 1 )
DO j = 1, SIZE ( ra, 2 )
xsum = xsum + ra(i,j)
END DO
END DO
RETURN
END SUBROUTINE rsum
Fortran90
Dynamische Speicherverwaltung (3)
Automatische Felder
SUBROUTINE sub ( n, a )
IMPLICIT NONE
INTEGER :: n
REAL, DIMENSION(n,n), INTENT(INOUT) :: a
REAL, DIMENSION(n,n) :: work1
! automatisch
REAL, DIMENSION(SIZE(a,1)) :: work2
! automatisch
...
RETURN
END SUBROUTINE sub
Fortran90
Feldverarbeitung - Intrinsics (1)
Reduktionen von Feldelementen
ALL, ANY, COUNT, PRODUCT, SUM,
MAXVAL, MINVAL, MAXLOC, MINLOC
Informationen über die Form eines Feldes
ALLOCATED, LBOUND, UBOUND, SHAPE, SIZE
Erstellen von Feldern
MERGE, PACK, UNPACK, SPREAD
Umformen von Feldern
RESHAPE
Feldverarbeitung
CSHIFT, EOSHIFT, TRANSPOSE
Feldarithmetik
DOT_PRODUCT, MATMUL
Achtung: Die Performance der Intrinsics ist nicht immer optimal !
(z.B. besser DGEMM aus einer optimierten Blas-Bibliothek als MATMUL
nehmen)
Fortran90
Feldverarbeitung - Intrinsics (2)
Beispiele
REAL s, x(100)
s = SUM ( x, MASK = x > 0.0 )
REAL, DIMENSION(-3:4) :: x
INTEGER, DIMENSION(1) :: locmax
x = (/1.2,3.4,5.4,11.2,1.0,3.7,1.0,1.0/)
locmax = MAXLOC(x)
maxval = x(LBOUND(x) + locmax(1) - 1 )
! = (/4/)
Fortran90
Abgeleitete Typen
Abgeleitete Typen (derived types, Strukturen)
INTEGER, PARAMETER :: male=1, female=0
TYPE person
INTEGER :: ident
INTEGER :: sex
REAL :: salary
END TYPE person
TYPE (person), DIMENSION(100) :: group
TYPE (person) :: boss = person(1,female,100000.0)
group%sex = male
! alles Männer
group%sex(27) = female ! Huhn im Korb
group(1) = boss
Fortran90
Operatorüberladung
MODULE vector_module
TYPE vector
REAL :: x, y
END TYPE vector
INTERFACE OPERATOR (+)
! overloading operator +
MODULE PROCEDURE vector_add
END INTERFACE
CONTAINS
FUNCTION vector_add(v1, v2)
TYPE (vector) :: vector_add
TYPE (vector), INTENT(IN) :: v1, v2
vector_add%x = v1%x + v2%x
vector_add%y = v1%y + v2%y
END FUNCTION vector_add
END MODULE vector_module
Fortran90
Zeiger (1)
Zeiger (pointer), werden nicht als Zeiger auf Speicherplätze verwendet, sondern eher als
Alias-Bezeichnungen. Sie sind mit Vorsicht zu benutzen.
PROGRAM linked_list
TYPE node
INTEGER :: value
! data filed
TYPE (node), POINTER :: next
! pointer field
END TYPE node
INTEGER :: num, status
TYPE (node), POINTER :: head, tail, current
! build up the list
NULLIFY(head, tail)
! initially nullify the list (empty)
PRINT *, 'Type-in an integer number to build a linked list (0 to terminate)'
READ *, num
! read num from keyboard
IF (num /= 0) then
! if 0 is entered, do nothing
ALLOCATE(head, STAT = status)
! create the head of the list
IF (status > 0) STOP 'Fail to allocate a new node'
head%value = num
! give the value
NULLIFY(head%next)
! point to null
tail => head
! update tail of list
Fortran90
Zeiger (2)
! create rest of list
READ *, num
! read num from keyboard
IF (num == 0) EXIT
! until 0 is entered
ALLOCATE(current, STAT = status) ! create new node
IF (status > 0) STOP 'Fail to allocate a new node'
current%value = num
! giving the value
NULLIFY(current%next)
! point to null (end of list)
tail%next => current
! link to tail of list
tail => current
! update tail of list
END DO
END IF
DO
! transverse the list and print the values
current => head
! make current as alias of list
DO
IF (.NOT. ASSOCIATED(current)) EXIT ! exit if null pointer
PRINT *, current%value
! print the value
current => current%next
! make current alias of next node
END DO
END PROGRAM linked_list
Fortran90
Datentypvarianten
Der Datentypvarianten (KIND) erlaubt eine Mindestanzahl von signifikanten
Dezimalstellen anzufordern. Meist genügen REAL*4, REAL*8 etc.
Interessanter Fall: Ein Programm wird mit oder ohne Autodouble-Option übersetzt.
include ´mpif.h´
REAL, DIMENSION(:,:) :: x
INTEGER :: mpi_float
SELECT CASE (KIND(x))
CASE(4)
mpi_float = MPI_REAL
CASE(8)
mpi_float = MPI_DOUBLE_PRECISION
CASE DEFAULT
STOP ´real kind unsupported by MPI´
END SELECT
CALL MPI_SEND(x,SIZE(x),mpi_float,...)
Fortran90
Ein-/Ausgabe
nicht vorrückende Ein-/Ausgabeanweisung
WRITE (*,´(„Eingabe? “)´,ADVANCE=´NO´)
READ(*,´(I5)´) n
neue OPEN-Parameter
POSITION = ASIS | REWIND | APPEND | UNDEFINED
ACTION = READ | WRITE | READWRITE | UNDEFINED
STATUS = OLD | NEW | SCRATCH | REPLACE | UNKNOWN
neue Format-Beschreiber
EN (engenieerung), ES (scientific),
B (binary), O (octal), Z (hex), G (generalized)
NAMELIST /listname/ a, i, x
READ ( unit, NML=listname)
Fortran90
Literatur / Weblinks
Fortran90 - Ein Nachschlagewerk, RRZN Hannover, SPR.F90 1, 8/92, im
Rechenzentrum erhältlich
Fortran90 - A conversion Course for Fortran77 Programmers - Student
Notes http://www.mcc.ac.uk/hpc/mantec/
http://www.uni-karlsruhe.de/~Fortran90/Tutorials/Manchester
Fortran95 - Fachwörterliste Englisch-Deutsch, RRZN Hannover, SPR.F95
2, 10/95
http://www.nsc.liu.se/~boein/f77to90/f77to90.html
Online Tutorial
Homepage von Wilhelm Gehrke mit zahlreichen weiteren Fortran-Links
http://www.unics.uni-hannover.de/rrzn/gehrke
Freier Fortran90-Compiler für Linux und Kommentar dazu
http://www.psrv.com
http://www.heise.de/ix/artikel/1998/08/068
User Notes on FortranProgramming
http://SunSITE.Informatik.RWTH-Aachen.DE/fortran
Weitere Links zum Thema Fortran
http://www.fortranlib.com/
http://www.uni-karlsruhe.de/~Fortran90/
http://studbolt.physast.uga.edu/templon/fortran.html

Documents pareils