Dan Nagle's Technical Site

Module fthreads Usage

Home --> Free Source Code --> fthreads --> fthreads Usage

Module fthreads Usage

This page is the entry point for the pages describing the module fthreads. This page contains links to the other pages, an introduction to programming using fthreads, a list of the types and constants defined by the module fthreads, and descriptions of the routines making up the fthreads trace facility. A selection of links is below.

Back to the Top

Introduction to fthreads

A process is run by the operating system. Every process has its associated memory, executes its own instructions, and has a current state. A thread is a separate execution of the instructions, each thread has an associated state. (Examples of state are "executing", "suspended awaiting I/O", "arithmetic exception", and so on.) Each thread is scheduled by the operating system to run independently of other threads. A team is a group of threads, defined by by the programmer via fthreads. A synchronization object is a barrier, an event, a mutex or a semaphore.

When the Win32 system starts a process, it begins executing a thread called the primary thread. The primary thread can then start the running of other threads. Fortran programmers are mainly interested in using these extra threads to accellerate execution of numerically intensive programs. fthreads calls these extra threads worker threads. The idea is for your primary thread (the first thread, started by the operating system) to initialize the fthreads system, initialize any synchronization objects needed, start worker threads to perform the calculation, wait for the worker threads to complete their calculation, gather any statistics the programmer wants about program execution, and then terminate the fthreads system and print any statistics gathered.

fthreads also provides a trace facility to enable the programmer to follow the execution of a program using fthreads. Use of the trace facility is not necessary- to use it, simply declare one or more trace variables of type trace_t, initialize them via trace_init() and pass them to the various fthreads routines the program calls. The programmer can also add messages via trace_msg(). A trace variable is a variable of type trace_t, this type is defined in the fthreads module and so is available whenever fthreads is being used. Most fthreads routines accept a trace variable to trace their activities. The trace variable has a circular buffer of user defined size, set by the call to trace_init(). Each message has the date, time and system clock added to the message. All trace messages from fthreads routines contain the name of the routine making the message.

In order to take full advantage of the modern Fortran interface system, fthreads defines several types which are used to define variables used for different purposes. In addition to the above memtioned trace_t, fthreads also defines thread variables of type thread_t, barrier variables of type barrier_t, event variables of type event_t, mutex variables of type mutex_t and semaphore variables of type semaphore_t. Use of these types enables the compiler to check for correct usage of fthreads routines, so many errors may be caught at compile time, rather than as the cause of an obscure run time exception.

The execution of a process using fthreads will follow this general flow:

  1. (Optionally) declare any trace variables you want and initialize them by calling trace_init().
  2. Initialize fthreads by calling fthread_init(), declaring how many threads, teams, and each kind of synchronization objects you want. A program may pass a trace variable to fthread_init() to record the initialization details.
  3. (Optionally) declare any team variables you want and initialize them by calling team_init().
  4. (Optionally) declare any synchronization object variables you want and initialize them by calling barrier_init(), event_init(), mutex_init() and semaphore_init() as needed.
  5. Declare your thread variables and create your threads by calling thread_create(). The threads will start to execute independently as soon as they are created (which is why any teams and synchronation objects used must be created beforehand).
  6. Wait for your threads to finish executing by calling thread_wait() to wait for one thread or thread_waitall() to wait for a team of threads.
  7. (Optionally) gather any statistics from the fthreads system (fthread_status()), teams (team_status()), threads (thread_status()) and synchronization objects (via barrier_status(), event_status(), mutex_status() or semaphore_status()). Statistics may be gathered from a trace variable by calling trace_status().
  8. (Optionally) terminate fthreads by calling fthread_end(). This step deallocated fthreads data structures, so fthreads can't be used past this point (except that trace variables declared in the primary thread are available).
  9. (Optionally) print out any trace variables you used by calling trace_print().

Back to the Top

fthreads Types

The fthreads defines several derived types. These types are listed below. They are available to the programmer whenever the fthreads module is used.

trace_t
is used to declare a trace variable which implements the trace facility.
thread_t
is used to declare a thread variable which identifies a thread.
team_t
is used to declare a team of threads chosen by the programmer.
barrier_t
is used to declare a barrier synchronization object.
event_t
is used to declare an event synchronization object.
mutex_t
is used to declare a mutex synchronization object.
semaphore_t
is used to declare a semaphore synchronization object.

Back to the Top

fthreads Constants

The fthreads constants include status and error codes, and Win32 defined values. These constants are listed below. Other fthreads constants have an fthread defined derived type, as noted below.

win32_priority_lowest
The lowest thread priority within the process.
win32_priority_below_normal
A low thread priority within the process.
win32_priority_normal
The normal thread priority within the process.
win32_priority_above_normal
A high thread priority within the process.
win32_priority_highest
The highest thread priority within the process.
fthread_ok
The success status value returned by fthreads routines.
fthread_buffer_wrap
The (circular) message buffer of a trace variable has filled and now new messages are overwriting older ones.
fthread_error_number
The error code meaning that an unusable value was passed to an fthreads routine.
fthread_error_state
The error code meaning that fthreads was initialized twice or terminated when not initialized.
fthread_error_allocate
The error code meaning that a Fortran allocate statement returned an error status.
fthread_error_syscall
The error code meaning that a Win32 system call returned an error code.
fthread_error_active
The error code meaning that an attempt was made to get a thread's return value or execution time while the thread was still running.
fthread_error_not_primary
The error code meaning that a worker thread attempted an action allowed only by the primary thread.
fthread_error_io
The error code meaning that a Fortran I/O statement returned an error status.
fthread_error_team
The error code meaning that a thread attempted to use a synchronization object belonging to a team the where the thread isn't a member.
primary_id
The thread id of the primary thread.
primary
The thread_t primary thread variable.
all_threads_id
The team id of the fthreads defined team which includes all threads.
all_threads
The team_t team variable of the fthreads defined team which includes all threads.
all_workers_id
The team id of the fthreads defined team which includes all worker threads, that is, all threads except the primary thread.
all_workers
The team_t team variable of the fthreads defined team which includes all worker threads, that is, all threads except the primary thread.

Back to the Top

Trace Routines

The trace routines are listed below, together with their interfaces. Note that many arguments are optional.

trace_init()

The trace_init() routine initializes a trace variable.

interface
   subroutine trace_init( max_msgs, &
              lock, trace_v, flag)
      integer, intent( in) :: max_msgs
      logical, optional, &
               intent( in) :: lock
      type( trace_t), &
            intent( out) :: trace_v
      integer, optional, &
               intent( out) :: flag
   end subroutine trace_init
end interface
	

The trace variable trace_v is initialized with max_msgs entries for messages, if lock is true, the access to the trace variable is single threaded so the trace variable may be used from different threads. The integer flag should return with a value of fthread_ok.

Back to the Top

trace_msg()

The trace_msg() adds a message to a trace variable.

interface
   subroutine trace_msg( msg, code, &
                         trace_v, flag)
      character( len= *), &
                 intent( in) :: msg
      integer, optional, &
               intent( in) :: code
      type( trace_t), &
            intent( inout) :: trace_v
      integer, optional, &
               intent( out) :: flag
   end subroutine trace_msg
end interface
	

The message msg is added to the trace variable trace_v with integer code formatted at the end of msg. If the trace variable is single threaded, it is locked. The msg has the date and time added at the beginning. The integer flag should return with a value of fthread_ok, or fthread_buffer_wrapped if the (circular) buffer is full and a message was overwritten.

Back to the Top

trace_print()

The trace_print() prints the messages in a trace variable.

interface
   subroutine trace_print( log_unit, &
              trace_v, printed, flag)
      integer, optional, &
               intent( in) :: log_unit
      type( trace_t), &
            intent( inout) :: trace_v
      integer, optional, &
               intent( out) :: printed
      integer, optional, &
               intent( out) :: flag
   end subroutine trace_print
end interface
			

The messages in the trace variable trace_v are printed on the unit log_unit. The number printed is returned in the integer printed, this number is at most max_msgs (see trace_init() above). The integer flag returns the status of the operation.

Back to the Top

trace_status()

The trace_status() return trace variable statistics.

interface
   subroutine trace_status( trace_v, &
              msgs, printed, size, count)
      type( trace_t), &
            intent( in) :: trace_v
      integer, optional, &
               intent( out) :: msgs
      integer, optional, &
               intent( out) :: printed
      integer, optional, &
               intent( out) :: size
      integer, optional, &
               intent( out) :: count
   end subroutine trace_status
end interface
	

The routine trace_status() returns the trace variable's statistics. The optional integer msgs returns the total number of messages which have been recorded in the trace variable. The optional integer printed returns the total number of messages printed. The optional integer size returns the number of messages the trace variable is capable of holding (set by the call to trace_init()). The optional integer count returns the number of messages currently in the trace variable, note that this message may be inaccurate in other threads are adding or printing messages.

Back to the Top

Please see our Fact Sheet, or E-mail me for more information.


Home - Fact Sheet - Free Source Code - Fortran Links - Email me

Back to the Top