gfortran.org


Using More Than 1 Core, The Old School Way

The concept is simple:

Break up your problem into N threads of execution.
Place your interface between threads into a named COMMON block.
Code each of your 'threads of execution' as a fortran main.
Tie each main program to it's own CPU. 
Use a linker directive to place the named COMMON block at an arbitrary
cirtual address in each fortran main. (Identical)
Use POSIX shared memory to tie the named COMMON block to a fixed address
in each program.

Example



[bdavis@localhost ~]$ cat a.f
       IMPLICIT NONE
       CHARACTER*16 S
       INTEGER*4 I,STAT,KEY,SIZE,ADDR
       DATA KEY  / Z'FFF100??' /
       DATA SIZE / Z'00001000' /
       DATA ADDR / Z'40200000' /
       COMMON / GLOBAL01?? / S
       CALL X_INCLD(KEY,ADDR,SIZE,STAT)
       IF (STAT.EQ.0) THEN
           PRINT*
           PRINT*
           PRINT*
           DO I=1,30
                PRINT*,'S from shared memory is ',S
                CALL SLEEP(1)
           ENDDO
       END IF
       END
[bdavis@localhost ~]$ cat b.f
       IMPLICIT NONE
       CHARACTER*16 S
       INTEGER*4 I,STAT,KEY,SIZE,ADDR
       DATA KEY  / Z'FFF100??' /
       DATA SIZE / Z'00001000' /
       DATA ADDR / Z'40200000' /
       COMMON / GLOBAL01?? / S^M
       CALL X_INCLD(KEY,ADDR,SIZE,STAT)
       IF (STAT.EQ.0) THEN
           DO I=1,30
                WRITE(S,*)'COUNT IS ',I
                CALL SLEEP(2)
           ENDDO
       END IF
       END
[bdavis@localhost ~]$ cat shared_mem.c
#include 
#include 
#include 
#include 
#include 
void x_incld__ (int *key, int *addr, int *size, int *status) {
  int shmid;
  if ((shmid = shmget (*key, *size, IPC_CREAT | IPC_EXCL | 0666)) == -1)^M
    {
      shmid = shmget (*key, *size, 0);
    }
  *status = (int) shmat (shmid, (const void *) *addr, SHM_REMAP);
  if (*status == *addr)
    {
      *status = 0;
    }
  else
    {
      *status = -1;
    }
  return;
}
[bdavis@localhost ~]$ g77 -Wall -g -o a a.f shared_mem.c -Wl,--defsym -Wl,global01_=0x40200000
[bdavis@localhost ~]$ g77 -Wall -g -o b b.f shared_mem.c -Wl,--defsym -Wl,global01_=0x40200000
[bdavis@localhost ~]$ ./a&;./b& [1] 7234 [2] 7235
[bdavis@localhost ~]$
 S from shared memory is  COUNT IS  1
 S from shared memory is  COUNT IS  1
 S from shared memory is  COUNT IS  2
 S from shared memory is  COUNT IS  2
 S from shared memory is  COUNT IS  3
 S from shared memory is  COUNT IS  3
 S from shared memory is  COUNT IS  4
 S from shared memory is  COUNT IS  4
 S from shared memory is  COUNT IS  5
 S from shared memory is  COUNT IS  5
 S from shared memory is  COUNT IS  6
 S from shared memory is  COUNT IS  6
 S from shared memory is  COUNT IS  7
 S from shared memory is  COUNT IS  7
 S from shared memory is  COUNT IS  8
 S from shared memory is  COUNT IS  8
 S from shared memory is  COUNT IS  9
 S from shared memory is  COUNT IS  9

This technique has been used since the 1970's and was very popular on several
mini-computers of the era.  Some fortran dialects provided direct support for
the mapping of common blocks between tasks.


On this site

Contact

bdavis9659@sbcglobal.net
Google