Next: , Up: API Reference


A.1 UPC Measurement API

The prototypes for the UPC measurement API are shown below:

     #include <pupc.h>
     
     int pupc_control(int on);
     
     unsigned int pupc_create_event(const char *name, const char *desc);
     
     void pupc_event_start(unsigned int evttag, ...);
     void pupc_event_end(unsigned int evttag, ...);
     void pupc_event_atomic(unsigned int evttag, ...);

A.1.1 UPC API Description

These functions may be used to turn data measurement on and off at runtime, and to manually instrument your program to notify PPW about application-specific events, such as when your program enters certain phases of communication or computation.

If you plan on using your code with systems that might not support these functions, such as non-GASP compilers, you may protect each part of your program that is related to these functions by checking for the existence of the __UPC_PUPC__ macro. Any UPC compiler or performance tool supporting the measurement API described here will define the __UPC_PUPC__ macro, so protecting any manual instrumentation with #ifdefs will allow your code to remain portable to systems not supporting this API.

The ‘pupc_control’ function allows a programmer to turn data collection on and off at runtime. If the on parameter is zero, PPW will stop recording all data measurements until another call to ‘pupc_control’ is made with a non-zero value for on. This function allows you to restrict performance data measurements to particular parts of your program, which may be useful if you are only interested in tuning specific parts of your program.

The ‘pupc_create_event’ function instructs PPW to generate a new user-defined event ID named name with a description desc, which is then returned. This event ID may correspond to a region of code or a program phase; it is entirely up to the programmer how to use event IDs to record performance data for their program.

Once a new event ID has been created with the ‘pupc_create_event’ function, that event ID may be used with the ‘pupc_event’ family of functions to denote entry/exit/atomic operations related to this event. The ‘pupc_event_start’ function instructs PPW that the event has just begun execution, and the ‘pupc_event_end’ function instructs PPW that the event has just finished executing.

The desc string given to ‘pupc_create_event’ may contain printf(3)-style format strings. If so, this desc parameter will be used to interpret any additional arguments given to the ‘pupc_event’ family of functions beyond the evttag event identifier. A quick example:

     ...
     unsigned int myev;
     myev = pupc_create_event("Phase 1", "%d - %s");
     pupc_start_event(myev, 1, "String data 1");
     ...
     pupc_end_event(myev, 2, "String data 2");
     ...

If the desc argument is not NULL, every call to the ‘pupc_event’ family with that event ID must follow the formatting dictated by the original desc argument or PPW may not behave properly (or may crash!).

The ‘pupc_event_atomic’ function is a special function that instructs PPW that an atomic operation has just occurred on this event. This event is useful if you want to record event data while the program is in the middle of executing that event, or you just want to record the number of times some particular event occurred without having to make a call to both ‘pupc_event_start’ and ‘pupc_event_end’.

By default, PPW will treat all user events the same way it treats functions, so all calls the ‘pupc_event’ family of functions must be properly nested. That is, any call to ‘pupc_event_start’ must have a corresponding call to ‘pupc_event_end’ with the same event ID. If you do not do this, you will experience warnings similar to the following:

     ... unbalanced start & end timer...

This will most likely occur if you insert a ‘pupc_event_start’ call at the beginning of a function but do not place a ‘pupc_event_end’ at every possible function exit.

A.1.2 UPC API Examples

As an example, suppose you've written a UPC program that resembles the following structure:

     #include <upc.h>
     
     int main() {
       /* initialization phase */
       /* ... */
       upc_barrier;
     
       /* computation phase with N iterations */
       for (i = 0; i < N; i++) {
         /* ... */
         upc_barrier;
       }
     
       /* communication phase */
       /* ... */
       upc_barrier;
     
       return 0;
     }

and you compile this program with ppwupcc --inst-functions main.upc. When viewing this performance data, you will get information about how long each thread spent executing ‘main’, but not much information about each of the phases within your program. If your computation phase has a load-balancing problem, this might be hard to detect just by examining performance data for ‘main’. Similarly, if you have a complicated program structure where program phases are not neatly divided into function calls, then you will have a hard time localizing performance problems to particular phases of your program's execution.

Using PPW's measurement API, you would do this:

     #include <upc.h>
     #include <pupc.h>
     
     int main() {
       unsigned int evin, evcp, evcm;
     
       evin = pupc_create_event("Init phase", NULL);
       evcp = pupc_create_event("Compute phase", "%d");
       evcm = pupc_create_event("Comm phase", NULL);
     
       /* initialization phase */
       pupc_event_start(evin);
       /* ... */
       upc_barrier;
       pupc_event_end(evin);
     
       pupc_event_start(evcp, -1);
       /* computation phase with N iterations */
       for (i = 0; i < N; i++) {
         pupc_event_atomic(evcp, i);
         /* ... */
         upc_barrier;
       }
       pupc_event_end(evcp, -1);
     
       /* communication phase */
       pupc_event_start(evcm);
       /* ... */
       upc_barrier;
       pupc_event_end(evcm);
     
       return 0;
     }

A.1.3 UPC API Notes

PPW does not currently record any of the user-supplied data that is passed into the ‘pupc_event’ family of functions. This means that calling ‘pupc_event_atomic’ essentially is a no-op.

In the future, PPW may treat the desc argument of ‘pupc_create_event’ in a special way, or allow users to denote the iteration number of a program phase using the ‘pupc_event_atomic’ function.

PPW might be extended to allow arbitrary nesting of user events. See bug #71 on our Bugzilla website.

Finally, having to manually instrument your UPC code is a pain, and it would be nice if PPW could use a simple barrier to phase matching to automatically detect most of the program's phases. See bug #88 on our Bugzilla website.