OpenMP support
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.
Ok, I got more input than I'd expected and less time than I wished. :) Anyway, against my own objection, the idea of enclosing the parallel code into local functions looks very appealing, so I've changed the example accordingly.
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 haveshared
context. // This would include the function's parameters then... begin parallel // Variables declared here haveprivate
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.
There's a problem with that: We have a parallel for-loop. You don't want to turn for-loops into functions, do you? --V.hoefler 20:09, 27 July 2006 (CEST)
More constructs
To be continued...
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); 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>