• No results found

The GUM runtime system possesses many attractive aspects for the parallel reduction of functional programs. Program annotations have been implemented and this implementation also provides the framework for additional annotations. The existing

par annotation is sufficient not only for the identification of parallelism but also as the

basis for speculative evaluation. It is, however, insufficiently flexible for the purposes of effective speculative evaluation.

The execution of some programs will benefit from the ability to place parallel threads on particular processing elements. Also, some programs will benefit from the ability to have components of the program executed in a round-robin manner. For

profiling/tracing/debugging purposes being able to associate the thread with a numeric identifier or string label is particularly useful. All of these features have been added to the GPH language and the GUM runtime system in this implementation.

The greatest impact on effective speculative evaluation as supported by annotations, is the addition of priorities to the annotation (as currently supported by GranSim [Loidl 1998]). The priority value may be used by the programmer to indicate many things (as suggested in Chapter Three). Examples include the chance of execution under

conservative evaluation, the granularity of the expression, an ‘incentive’ indicating the latency penalty of subsequent conservative evaluation, or the dependence upon

referenced data. The scheme for representing the priority is important too (as discussed in Section 3·3); but this implementation has been built using the Percentiles scheme within GPH and within GUM — although the external and internal representations are fully decoupled.

Finally, the inclusion of an annotation that provides the programmer with the power to include all of these features provides full speculative evaluation flexibility to every

Chapter Seven: Effective Management of Speculative Evaluation Haskell expression, and thus the opportunity to the programmer to finely tune the execution behaviour of his/her program.

Two mechanisms for tracking the priority of a thread were introduced in Section 7·4·5·3: calculation and derivation. Derivation offers gains if priorities change often and rescheduling occurs relatively less often since no calculations are required when the priorities change, however, pointers must be followed when a thread is considered for rescheduling. In the multicomputer environment, calculation is the clear winner due to the network latency. The calculation scheme requires the values to be stored in

formulae, rather than references to the values, so that calculations are required whenever a priority changes but no processing is necessary when a thread’s definitive priority is demanded. The calculation scheme also mandates communication when the priority of a remote thread changes; the derivation scheme requires this only when the definitive priority of a thread is required. If thread priorities change often, the

communication under the latter scheme will be significantly less than in the former scheme, but again, this communication will occur at a time when it cannot readily be afforded. A multiprocessor architecture would be more suitable for derivation — and even then a bottleneck may be created if many threads require access to the stored priority of their parent.

The GUM runtime system, in the form obtainable from the University of Glasgow [AQUA 1996], selects the first sparkable spark from the spark pool to be converted to a thread. There is no indication of which spark would be more usefully evaluated; the only criterion for the selection of a spark is age. In fact, it is possible that the thread giving rise to the creation of the spark has already completed evaluation of the

annotated expression. If this is the case, spark selection incurs a check for sparkability which will indicate unsuitability and the next spark will be checked, and so on.

Regardless of the issues of last-in-first-out versus first-in-first-out spark selection, the inclusion of priorities will improve speculative evaluation effectiveness.

In the same vein, thread insertion in the original GUM runtime system is also first-in- first-out. There is no discernment between the main thread and those created through sparking. There is no discernment between any of the threads created through

sparking. All threads compete equally for processing resources — discrimination between threads is inappropriate as all threads are mandatory. In the extended

implementation of the GUM runtime system, threads possess priorities which allow positive discrimination for mandatory threads (whether the thread is the main thread or not does not matter) over speculative threads. Moreover, irrelevant threads are not scheduled unless the task would otherwise be idle. The concentration on evaluating only mandatory threads wherever possible ensures that the evaluation of needed

program components occurs unhindered, and that where extra processing resources are available, these are allocated to the threads most deserving of attention.

The last-in-first-out, unfair thread selection model of the original GUM runtime system is retained in this implementation, but it is augmented by first-in-first-out, fair

scheduling for threads within the same thread family. This ensures domination of the processing element does not occur which may otherwise result in the unnecessary non- termination of the program. The scheduler remains pre-emptive with time-slicing utilised to allow the task to alternate between communications processing and evaluation. Having a pre-emptive scheduler also allows modifications to occur to threads while no thread is executing and thus avoids the chasing problem observed and reported by Partridge [Partridge 1991].

7·7 Summary

It is evident that all modifications to the GUM runtime system have been motivated by the goal of improving the speculative evaluation of closures. It is equally evident that every such modification has been designed and written in a manner such that the modification either has no impact on the evaluation of mandatory threads, or has a minimal impact on the evaluation of mandatory threads.

Many changes have been made to the GHC compiler to facilitate effective speculative evaluation. Some changes have occurred at the language level: five new annotations have been added to GPH and implemented in GHC and the GUM runtime system. Other changes have occurred internally but the programmer has control over their manifestation:

• the spark and thread formats have been greatly expanded and the spark and thread pool structures are prioritised;

Chapter Seven: Effective Management of Speculative Evaluation

• the programmer can indicate the potential usefulness (priority) of an expression and that priority will be used within the evaluation subsystem to control the scheduling of that expression;

• sparks can be executed locally, remotely on a specific processing element, or on any processing element;

• sparks and threads may be named with a numeric identifier as well as with a string label; and

• threads belonging to the same family are executed in a round-robin manner — in contrast to the unfair scheduling of threads that is the default.

To summarise, the changes described here increase the usefulness of the speculative evaluation system, and when speculative evaluation is not undertaken, the changes have little or no impact.

Chapter Eight: Effective Implementation of Speculative Evaluation

Chapter Eight: Effective Implementation of

Speculative Evaluation