Difference between revisions of "OpenMP support"

From Free Pascal wiki
Jump to navigationJump to search
(added nested procedure syntax)
Line 76: Line 76:
  
  
 +
=== Proposal 2: Using local functions ===
  
=== Proposal 2 ===
+
Instead of using new block types (like parallel), it uses a nested procedure, with the '''parallel''' modifier.
 +
 
 +
==== parallel ====
 +
 
 +
  <b>procedure</b> SubDomain (<b>var</b> x      : <b>array of</b> Float;
 +
                            istart  : Integer;
 +
                            ipoints : Integer);
 +
  <b>var</b>
 +
      i : Integer;
 +
  <b>begin</b>
 +
      <b>for</b> i := 0 <b>to</b> ipoints - 1 <b>do</b>
 +
        x[istart + i] := 123.456;
 +
  <b>end</b> <i>{SubDomain}</i>;
 +
 
 +
  <b>procedure</b> Sub (<b>var</b> x : <b>array of</b> Float);
 +
  <i>// Variables declared here should have </i><code><b>shared</b></code><i> context.</i>
 +
  <i>// This would include the function's parameters then...</i>
 +
    <b>procedure</b> ParallelBlock; <b>parallel</b>;
 +
    <b>var</b>   
 +
        iam    : Integer;
 +
        nt      : Integer;
 +
        ipoints : Integer;
 +
    <b>begin</b>
 +
          iam := OMP.Get_Thread_Num;  <i>// OMP library calls.</i>
 +
          nt  := OMP.Get_Num_Threads;
 +
         
 +
          ipoints := Length (x) <b>div</b> nt; <i>// size of partition</i>
 +
          istart  := iam * ipoints;    <i>// starting array index</i>
 +
         
 +
          <b>if</b> iam = Pred (nt) <b>then</b>
 +
            ipoints := Length (x) - istart; <i>// last thread may do more</i>
 +
       
 +
          SubDomain (x, istart, ipoints);
 +
    <b>end</b>;
 +
 +
  <b>begin</b>
 +
        ParallelBlock;
 +
  <b>end</b> <i>{Sub}</i>;
 +
 
 +
  <b>var</b>
 +
      arr = <b>array</b>[0 .. 9999] <b>of</b> Float;
 +
  <b>begin</b> <i> // Main program</i>
 +
      Sub (arr);
 +
  <b>end</b>.
 +
 
 +
 
 +
 
 +
=== Proposal 3 ===
 
<not yet done>
 
<not yet done>

Revision as of 11:31, 26 July 2006

What is OpenMP?

OpenMP is an API accessed by language directives to do multi threaded programming, see also http://www.openmp.org. Currently, there is only OpenMP syntax defined for C and Fortran. This page tries to collect some stuff to settle down pascal syntax for it.

Pascal syntax for OpenMP

Proposal 1

Foreword

At first, I must admit that some parts of the OpenMP specification I still don't understand. They did a terrible good job throwing away all common terms ever used in multi threading context, and invented their own ones.

Syntax vs. Compiler directives

OpenMP for C and C++ is implemented by using compiler directives mainly due to the reasons of source code compatibility (or: standards compliance). So a conforming program is intended to behave the same regardless if the actual compiler compiling the program supports those special pragmas or not.

For FreePascal I don't think this is the way to go, because first it changes comments into code and second, it makes the program far less readable. For C programs this doesn't seem to be an issue, if you get my meaning. But in my opinion, readability is a far more important issue than compatibility to older/different compilers. If all else fails, a preprocessor could be provided to strip out the parallel specific stuff, as has been suggested by Marco.

Well, enough talk, I start with the easier directives which are luckily the more fundamental ones.

parallel

The parallel construct can only be used for a structured block. That means in Pascal it should be enclosed in some sort of begin/end pair anyway. So with this in mind, even the clauses that go with the original parallel construct could possibly be supported in a clean and structured way. So if you take a look at the A.4.1.c example of the OpenMP 2.5 specification, the Pascal version could look like this:

  procedure SubDomain (var x       : array of Float;
                           istart  : Integer;
                           ipoints : Integer)
  var
     i : Integer;
  begin
     for i := 0 to ipoints - 1 do
        x[istart + i] := 123.456;
  end {SubDomain};
  
  procedure Sub (var x : array of Float);
  // Variables declared here should have shared context.
  // This would include the function's parameters then...
  begin
     parallel
        // Variables declared here have private context.
        iam     : Integer;
        nt      : Integer;
        ipoints : Integer;
     begin // of parallel section
        iam := OMP.Get_Thread_Num;  // OMP library calls.
        nt  := OMP.Get_Num_Threads;
        
        ipoints := Length (x) div nt; // size of partition
        istart  := iam * ipoints;     // starting array index
        
        if iam = Pred (nt) then
           ipoints := Length (x) - istart; // last thread may do more
        
        SubDomain (x, istart, ipoints);
     end {parallel};
  end {Sub};
  
  var
     arr = array[0 .. 9999] of Float;
  begin  // Main program
     Sub (arr);
  end.

I don't like the idea of declaring variables inside the actual statments, this looks very unpascalish. Maybe we can find a way around it. --FPK 10:22, 26 July 2006 (CEST)

I agree with Florian that this is not the way to go. Why not require all parallelizable code to be in local functions ? After all, that's almost what you are doing: declaring a local function. That would be a simple extension of the current syntax. You have access to all local variables; all you'd need is to add a parallel keyword to the local function declaration.

More constructs

To be continued...

V.hoefler


Proposal 2: Using local functions

Instead of using new block types (like parallel), it uses a nested procedure, with the parallel modifier.

parallel

  procedure SubDomain (var x       : array of Float;
                           istart  : Integer;
                           ipoints : Integer); 
  var
     i : Integer;
  begin
     for i := 0 to ipoints - 1 do
        x[istart + i] := 123.456;
  end {SubDomain};
  
  procedure Sub (var x : array of Float);
  // Variables declared here should have shared context.
  // This would include the function's parameters then...
    procedure ParallelBlock; parallel;
    var     
        iam     : Integer;
        nt      : Integer;
        ipoints : Integer;
    begin
         iam := OMP.Get_Thread_Num;  // OMP library calls.
         nt  := OMP.Get_Num_Threads;
         
         ipoints := Length (x) div nt; // size of partition
         istart  := iam * ipoints;     // starting array index
         
         if iam = Pred (nt) then
            ipoints := Length (x) - istart; // last thread may do more
        
         SubDomain (x, istart, ipoints);
    end;

  begin
       ParallelBlock;
  end {Sub};
  
  var
     arr = array[0 .. 9999] of Float;
  begin  // Main program
     Sub (arr);
  end.


Proposal 3

<not yet done>