C++Guns – RoboBlog blogging the bot

20.10.2014

howto allocate array in C++ and pass it back to fortran

Filed under: Allgemein — Tags: , , — Thomas @ 12:10

test.cpp


#include < stdlib.h >

// fortran can only call C routines
extern "C" {
  // we need the address of the fortran pointer thus a pointer of a pointer.
  void myC_func(int **arr) {   
    // we cannot use new() here because fortran deallocate() use free() instead of delete[]
    *arr = (int*) malloc(12*sizeof(int));
    for(int i=0; i < 12; i++) {
      (*arr)[i] = i;
    }
  }
}

test.F90


! https://gcc.gnu.org/onlinedocs/gcc-4.6.2/gfortran/Working-with-Pointers.html

program main
  use iso_c_binding
  implicit none
  
  interface
    subroutine my_routine(arr) bind(c,name='myC_func')
      import :: c_ptr
      ! If a pointer is a dummy-argument of an interoperable procedure, 
      ! it usually has to be declared using the VALUE attribute. 
      ! void* matches TYPE(C_PTR), VALUE, while TYPE(C_PTR) alone matches void**. 
      type(c_ptr), intent(out) :: arr
    end subroutine
  end interface
  
  type(c_ptr) :: cptr
  integer,pointer :: fptr(:)
  
  ! allocate and fill cptr
  call my_routine(cptr)
  ! convert it to fortran pointer
  call c_f_pointer(cptr, fptr, [12])
  
  if(associated(fptr)) write(*,*) "associated"
  write(*,*) fptr
  deallocate(fptr)
  
end program main
g++ -Wall -Wextra -c test.cpp 
gfortran -Wall -Wextra -fcheck=all test.F90 test.o

valgrind ./a.out 
==5256== Memcheck, a memory error detector
==5256== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==5256== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==5256== Command: ./a.out
==5256== 
 associated
           0           1           2           3           4           5           6           7           8           9          10          11
==5256== 
==5256== HEAP SUMMARY:
==5256==     in use at exit: 0 bytes in 0 blocks
==5256==   total heap usage: 22 allocs, 22 frees, 11,874 bytes allocated
==5256== 
==5256== All heap blocks were freed -- no leaks are possible
==5256== 
==5256== For counts of detected and suppressed errors, rerun with: -v
==5256== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

03.09.2014

Fortran is DEAD!!

Filed under: Allgemein — Tags: , , — Thomas @ 19:09

Leute, ist sag es schon die ganze Zeit: Fortran ist eine tote Sprache.
Und damit meine ich nicht nur diese verbuggten Compiler. Oder dass es ewig braucht bis man ein neues Feature vom Compiler unterstützt wird. Im Fortran 2003 Standard sind zwar schön viele OO Ansatze festgelegt, aber ich kenne kein Compiler der den Standard nach 10 Jahre komplett unterstützt. Andere Sprachen sind schon 2 Schritte weiter.

Nein, diesmal habe ich viel bessere Argumente auf Lager. In dem Paper [1] wurden 800000 Software Projekte und 13000 Programmierer ausgewertet. Ich möchte nur zu einem Bild aus diesem Paper meine Meinung loswerden. Dieses da:

languages

Also, man sieht hier die Wahrscheinlichkeit, mit der man die Programmiersprache wechselt, wenn ein neues Projekt angefangen wird. Weis bis blau sind niedrige Wahrscheinlichkeiten und rot bis schwarz hohe.
Die Punkte auf der Diagonalen zeigen, dass man die Sprache NICHT wechselt.
Was haben wir denn da alles:
Rote Punkte sehe ich bei allesn *Basic Sprachen. Auch bei der C-Familie mit Java, Perl, PHP, Python bleiben die Programmierer bei ihrer Sprache.

Welche Sprachen bekommen Zuwachs? Das sieht man schön an den vertikalen Balken. Also Java, C/C++ und meinetwegen noch PHP. Das sind also die view Großen wohin die Programmierer wechseln, nachdem sie erkannten, dass ihre vorherige Wahl Schrott war. Tja, wagt es nicht das Wort gegen C++ zu erheben ;) Die Sprache ist sowas von geil und wird den ganzen anderen Schrott längerfristig schon tot trampeln ;)

Wohin rennen denn die Fortran Leute? JAVA. Ach ich lach mich kaputt. Das sind doch total verschiedene Welten.
Ich wette die Auftraggeber wollten parallelisierte hoch performante Software. Haben aber keine Programmierer gefunden der was aufn Kasten hat, und der Rest kam mit der Sprache nicht klar. Also wurde es wieder Java. Das ist ja bekannt und jeder kann es. Und jetzt ärgern die sich mit ihrere total aufgeblasenen, lahmen Software rum, HäHä.

Die *Basic sprachen sind auch alle hinfällig. Zwar wechseln die Leute hier nicht, aber es kommen auch keine neuen hinzu. Die Sprache stirbt also aus, wenn auch alle *Basic Programmierer ausgestorben sind. Sehr einfach Das ;)

[1] Empirical Analysis of Programming Language Adoption; Leo A. Meyerovich; Ariel S. Rabkin

01.09.2014

Fortran progressmeter nice code

Filed under: Allgemein — Tags: — Thomas @ 22:09



! use modulo to determine when to print progress
! not independet of called algorithm speed
! possible output:
! 0.0  % done
! 0.01 % done
! 0,02 % done
! 0,03 % done
! or only one output
! 80.0 % done
! We can do better!
subroutine variant1(n)
  implicit none
  integer, intent(in) :: n
  integer :: i
  
  do i=1, n
    if(mod(i, 1000) == 0) write(*,*) 100.0*i/n, "% done"
    
    ! call some algorithm
    ! ...
  end do
end subroutine

! check in every iteration if progress is 10%, 20% u.s.w.
! pro: independet of called algorithm speed
! contra: more code
! possible output:
! 10 % done
! 20 % done
! 30 % done
! 80 % done
! 90 % done
! We can do better!
subroutine variant2(n)
  implicit none
  integer, intent(in) :: n
  integer :: i
  real :: percent, thr
  
  thr = 1.0 / n * 100.0  
  do i=1, n
    percent = 100.0*i/n
    if(percent > 10.0 .and. percent < 10.0+thr) write(*,*) "10 % done"
    if(percent > 20.0 .and. percent < 20.0+thr) write(*,*) "20 % done"
    if(percent > 30.0 .and. percent < 30.0+thr) write(*,*) "30 % done"
    if(percent > 40.0 .and. percent < 40.0+thr) write(*,*) "40 % done"
    if(percent > 50.0 .and. percent < 50.0+thr) write(*,*) "50 % done"
    if(percent > 60.0 .and. percent < 60.0+thr) write(*,*) "60 % done"
    if(percent > 70.0 .and. percent < 70.0+thr) write(*,*) "70 % done"
    if(percent > 80.0 .and. percent < 80.0+thr) write(*,*) "80 % done"
    if(percent > 90.0 .and. percent < 90.0+thr) write(*,*) "90 % done"      
    
    ! call some algorithm
    ! ...
  end do
end subroutine

! recalc threshold in every iteration
! possible output:
! 10 % done
! 20 % done
! 30 % done
! ...
! 90 % done
! almost done!
! we have to avoid duplicate code; copy&paste erros
subroutine variant3(n)
  implicit none
  integer, intent(in) :: n
  integer :: i
  real :: percent
  integer :: thr
  
  thr = 10
  do i=1, n
    percent = 100.0*i/n
    if(percent > thr) then
      write(*,*) thr, "% done"
      thr = thr +  10
    endif
    
    ! call some algorithm
    ! ...
  end do
end subroutine


! to avoid duplicate code and copy&paste errors, we move the code into a class and provide a progress function as interface
module ProgressMeterClass
  implicit none
  private
  public :: createProgressMeter

  type, public :: ProgressMeter
      integer, private :: n
      integer, private :: thr
    contains

      procedure :: progress
  end type
  
  interface createProgressMeter
    module procedure newProgressMeter
  end interface

  contains

  function newProgressMeter(n) result(this)
    implicit none
    type(ProgressMeter) :: this
    integer, intent(in) :: n

    this%n = n
    this%thr = 10
  end function

  subroutine progress(this, i)
    implicit none
    class(ProgressMeter), intent(inout) :: this
    integer, intent(in) :: i

    if(100.0*i/this%n > this%thr) then
      write(*,*) this%thr, "% done"
      this%thr = this%thr + 10
    endif
  end subroutine
end module


!> we use OO techniques. The progressmeter code is now in the ProgressMeterClass module.
!> We simply create an object of this type and call progress() on it in every iteration
subroutine variant4(n)
  use ProgressMeterClass
  implicit none
  integer, intent(in) :: n
  integer :: i
  type(ProgressMeter) :: pm
  
  ! we can pass a step and filehandle variable too
  pm = createProgressMeter(n)
  do i=1, n
    call pm%progress(i)
    
    ! call some algorithm
    ! ...
  end do
end subroutine

program Progressmeter  
  implicit none
  integer :: n

  n = 10000000

!   call variant1(n)
!   call variant2(n)  
!   call variant3(n)  
  call variant4(n)  
end program

26.07.2014

Fortran Speicherverbraucht ermitteln

Filed under: Allgemein — Tags: , — Thomas @ 13:07

Wieviel Speicher verbraucht mein Programm? Die Frage ist nicht so einfach zu beantworten, denn es gibt kein Funktionsaufruf in C der bei jedem Compiler und jedem *unix funktioniert. Nach vielen googlen habe ich herausgefunden, dass es wohl am besten ist, die entsprechenden Datein in /proc zu parsen.

In /proc/self/status steht unter anderem auch der Speicherverbraucht dinne. Man kann auch /proc/self/statsm parsen, wenn man Lust hat.

kater@mintux:~$ gfortran -Wall -o procstat procstatus.F90
kater@mintux:~$ ./a.out 
 VM size:        43044  kB

Das komplette Programm ist im Anhang.
procstatus.F90

18.10.2013

dependency overview

Filed under: Allgemein — Tags: — Thomas @ 10:10

Ist es nicht grauenhaft ^^

pdlib

libunnamed

06.10.2012

Installing gcc, g++ and gfortran 4.8 from source

Filed under: Allgemein — Tags: , , , — Thomas @ 16:10

First read http://gcc.gnu.org/install/
Make sure you have all Prerequisites installed!

Download all files to ~/opt/downloads
Install all packages to ~/opt/

Download gcc 4.8 from ftp://ftp.gwdg.de/pub/misc/gcc/snapshots/LATEST-4.8/ and unpack it.


wget ftp://ftp.gwdg.de/pub/misc/gcc/snapshots/LATEST-4.8/gcc-4.8-20120930.tar.bz2
tar xjf gcc-4.8-20120930.tar.bz2 
cd gcc-4.8-20120930

Download several necessary librarys into the gcc source directory and unpack them.
They will be built together with GCC.


wget ftp://ftp.gmplib.org/pub/gmp-5.0.5/gmp-5.0.5.tar.bz2
tar xjf gmp-5.0.5.tar.bz2
ln -s gmp-5.0.5 gmp

wget http://www.mpfr.org/mpfr-current/mpfr-3.1.1.tar.bz2
tar xjf mpfr-3.1.1.tar.bz2 
ln -s mpfr-3.1.1 mpfr

wget http://www.multiprecision.org/mpc/download/mpc-1.0.1.tar.gz
tar xzf mpc-1.0.1.tar.gz
ln -s mpc-1.0.1 mpc

Now configure and build


mkdir $HOME/opt/downloads/gcc-4.8-build
cd $HOME/opt/downloads/gcc-4.8-build
../gcc-4.8-20120930/configure --prefix=$HOME/opt/gcc-4.8 --enable-threads --enable-languages=c,c++,fortran
make
make install

Troubleshooting
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory

These files are usually locates in /usr/lib32/ and/or /usr/lib/x86_64-linux-gnu/
Add this to your .bashrc


export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LIBRARY_PATH

23.08.2012

Farbige Konsolenausgabe

Filed under: Allgemein — Tags: , , — Thomas @ 09:08

Farbe in der Konsole ist nicht schwer.
Beispiele in C und Fortran:


#include < unistd.h >

void resetFont() {
    if (isatty (fileno (stdout)))
        std::cout << "\e[0m";
}

void setFontRed() {
    if (isatty (fileno (stdout)))
        std::cout << "\e[1;31m";
}

void setFontGreen() {
    if (isatty (fileno (stdout)))
        std::cout << "\e[32m";
}

subroutine resetFont()
  implicit none
  ! this stuff is to print an escape sequenz and omit a newline
  write(*,'(A)', advance='no') achar(27)//"[0m"
end subroutine

subroutine setFontRed()
  implicit none
  write(*,'(A)', advance='no') achar(27)//"[1;31m"
  end subroutine

subroutine setFontGreen()
  implicit none
  write(*,'(A)', advance='no') achar(27)//"[32m";
end subroutine

Da Fortran per default keine Escape Sequenzen interpretiert (man muss das per Compiler Flag einschalten), kann man die achar() Funktion nutzen. Sie wandelt ein Integer auch in nicht-druckbare ASCII Zeichen um.

Auf diese Weise kann man sich auch eine gotoxy() Funktion bauen.

04.04.2012

Scheiß Fortran

Filed under: Allgemein — Tags: — Thomas @ 10:04

Ich hasse es, wirklich.
Welche Ausgabe erwartet ihr bei diesem Programm?


subroutine func()
  implicit none
  real :: time = 0;
  time = time + 1
  write(*,*) time
end subroutine

program test
  implicit none
  integer :: i
  do i = 1, 10
    call func()
  end do
end

Zehn mal die Ausgabe von "1"?
Nein, falsch!

thomas@cluster:~$ ./a.out 
   1.000000    
   2.000000    
   3.000000    
   4.000000    
   5.000000    
   6.000000    
   7.000000    
   8.000000    
   9.000000    
   10.00000 

Dann ist time also keine lokale Variable die bei jedem Aufruf von func() auf dem Stack gelegt wird? Und schon garnicht wird sie mit 0 initialisiert. Ist sie static und existiert die ganze Zeit über? Dann aber nicht auf dem Stack. Das nervt...

// edit
Die Variable wird statisch, sobald man sie bei der deklaration auch initialisiert.
http://www.math.uni-leipzig.de/~hellmund/Vorlesung/scr4.pdf Seite 25 und 26

Durch die Initialisierung wird die entsprechende Variable statisch! Die Initialisierung wird nur einmal, beim Programmstart, durchgeführt.
...
Variablen sind statisch, wenn sie
a) das save-Attribut tragen
integer, save :: j
b) bei der De?nition initialisiert werden (s. oben) oder
c) nach der De?nition mit einer data-Anweisung initialisiert werden.

« Newer Posts

Powered by WordPress