This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[gomp] Challenges in Implementing OpenMP
- From: Scott Robert Ladd <coyote at coyotegulch dot com>
- To: gcc mailing list <gcc at gcc dot gnu dot org>
- Date: Wed, 13 Oct 2004 13:01:22 -0400
- Subject: [gomp] Challenges in Implementing OpenMP
For those unfamiliar with OpenMP, I direct you to http://www.openmp.org.
In a nutshell, OpenMP defines a set of language extensions that simplify
parallel programming in C, C++, and Fortran. GOMP is the project
bringing that technology to the GCC compilers.
What I'm looking for at the moment are comments from the GCC community
in regard to the best approach for implementing OpenMP. Obviously,
changes need to be made in the parsers to recognize OpenMP pragmas and
comments; however, the implication of such directives is somewhat less
obvious.
OpenMP directives result in significant changes to the affected code.
Take, for example, this OpenMP version of "Hello, World", in C:
#include "stdio.h"
int main(void)
{
#pragma omp parallel
puts("Hello, World!\n");
return 0;
}
Using fork/wait mechanics, the compiler needs to translate this into
something like:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
// probably not portable
long num_procs = sysconf(_SC_NPROCESSORS_CONF);
printf("number of processors = %ld\n",num_procs);
long n;
for (n = 0; n < num_procs; ++n)
{
// create compile process and wait for it to finish
pid_t child_pid;
int child_result;
child_pid = fork();
// if this is a child, display our message
if (child_pid == 0)
{
puts("Hello, World!\n");
exit(0);
}
}
// wait for the right number of processes to exit
for (n = 0; n < num_procs; ++n)
wait(NULL);
return 0;
}
If pthreads are the target, the code would look like this:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// this function encapsulates the parallel region defined by
// the OpenMP pragma
void * par_proc(void * arg)
{
puts("Hello, World!\n");
return NULL;
}
int main(void)
{
// Linux-specific; OpenMP would also check environment settings here
long num_procs = sysconf(_SC_NPROCESSORS_CONF);
int n;
// an array of thread ids
pthread_t * thread_ids = (pthread_t *)malloc(sizeof(pthread_t)
* num_procs);
// for each processor...
for (n = 0; n < num_procs; ++n)
{
// launch a thread, storing its id in the list
pthread_create(&thread_ids[n],NULL,par_proc,NULL);
}
// wait for threads to finish
for (n = 0; n < num_procs; ++n)
{
// wait for each thread in succession
pthread_join(thread_ids[n],NULL);
}
// clean up and exit
free(thread_ids);
return 0;
}
Essentially, OpenMP restructures the original code. The above example is
incredibly simple, and only touches the surface of OpenMP's
complexities. For example, OpenMP directives often contain clauses that
define variable sharing among threads.
My feeling is that OpenMP processing should take place in the language
parser. Given the differences in the parsers for C and C++, this looks
to require separate modifications to those compilers. The implementation
for Fortran will, of course, be based on gfortran.
An additional concern is to make GNU OpenMP portable across most
platforms. This at least needs to be considered during the design phase;
the initial implementation would likely be for i686 and x86_64 (Linux
and Windows) platforms, simply based on the availability of developers
and hardware.
Following the practice of commercial compilers, I envision a "-fopenmp"
switch that will enable OpenMP parsing on platforms that support it.
Perhaps this option would have arguments, as in -fopenmp=pthreads or
-fopenmp=fork. Or, for simplicity's sake, we can stick just to pthreads.
The issues above are representative of the questions faced by the GOMP
group.
Considered comments appreciated.
--
Scott Robert Ladd
site: http://www.coyotegulch.com
blog: http://chaoticcoyote.blogspot.com