Overview

The SPE Runtime Management Library (libspe) is the standardized low-level application programming interface (API) that enables application access to the Cell BE SPEs. This library provides an API that is neutral with respect to the underlying operating system and its methods to manage SPEs.

Implementations of libspe can provide additional functionality that enables access to operating system or implementation-dependent aspects of SPE runtime management.
Note: This functionality is not subject to standardization in this document and its use can lead to non-portable code and dependencies on certain implemented versions of the library.

In general, applications do not have control over the physical SPE system resources. The operating system manages these resources. Applications manage and use software constructs called SPE contexts. These SPE contexts are a logical representation of an SPE and are the base object on which libspe operates. The operating system schedules SPE contexts from all running applications onto the physical SPE resources in the system for execution according to the scheduling priorities and policies associated with the runable SPE contexts.

libspe also provides the means for communication and data transfer between PPE threads and SPEs.

The basic scheme for a simple application using an SPE is as follows:
  1. Create an SPE context.
  2. Load an SPE executable object into the SPE context local store.
  3. Run the SPE context. This transfers control to the operating system, which requests the actual scheduling of the context onto a physical SPE in the system.
  4. Destroy the SPE context.
Note: Step 3 represents a synchronous call to the operating system. The calling application blocks until the SPE stops executing and the operating system returns from the system call that invoked the SPE execution.

Using multiple SPEs concurrently

Many applications need to use multiple SPEs concurrently. In this case, the application must create at least as many threads as concurrent SPE contexts are required. Each of these threads may run a single SPE context at a time. If N concurrent SPE contexts are needed, it is common to have a main application thread plus N threads dedicated to SPE context execution.

The basic scheme for a simple application running N SPE contexts is as follows:
  1. Create N SPE contexts.
  2. Load the appropriate SPE executable object into each SPE context’s local store.
  3. Create N threads:
    1. In each of these threads run one of the SPE contexts.
    2. Stop thread.
  4. Wait for all N threads to stop.
  5. Destroy all N SPE contexts.

Other schemes are also possible and, depending on the application, potentially more suitable.

PPE functions

To provide this functionality, libspe consists of the following sets of PPE (PowerPC® Processing Element) functions to:
  • Create and destroy SPE and gang contexts
  • Load SPE objects into SPE local store memory for execution
  • Start the execution of SPE programs and to obtain information about reasons why an SPE has stopped running
  • Receive asynchronous events generated by an SPE
  • Access the MFC (Memory Flow Control) problem state facilities, which includes:
    • MFC proxy command issue
    • MFC proxy tag-group completion facility
    • Mailbox facility
    • SPE signal notification facility
  • Enable direct application access to an SPE’s local store and problem state areas
  • Register PPE-assisted library calls for an SPE program

Terminology

Library Name(s)
libspe2
Header File(s)
<libspe2.h>

For a full list of terms, see Glossary

Example

The following example shows how to load and run a simple SPE executable "hello".

Example 1: Run the simple SPE program "hello"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "libspe2.h"

int main(void)
{
        spe_context_ptr_t ctx;
        int flags = 0;
        unsigned int entry = SPE_DEFAULT_ENTRY;
        void * argp = NULL;
        void * envp = NULL;
        spe_program_handle_t * program;
        spe_stop_info_t stop_info;
        int rc;

        program = spe_image_open("hello");
        if (!program) {
                perror("spe_open_image");
                return -1;
        }

        ctx = spe_context_create(flags, NULL);
        if (ctx == NULL) {
                perror("spe_context_create");
                return -2;
        }
        if (spe_program_load(ctx, program)) {
                perror("spe_program_load");
                return -3;
        }
        rc = spe_context_run(ctx, &entry, 0, argp, envp, &stop_info);
        if (rc < 0)
                perror("spe_context_run");

        spe_context_destroy(ctx);

        return 0;
}

The following simple multi-threaded example shows how an application can run the SPE program "hello" on multiple SPEs concurrently:

Example 2: Simple multi-threaded example
#include <stdlib.h>
#include <pthread.h>
#include "libspe2.h"

struct thread_args {
        struct spe_context * ctx;
        void * argp;
        void * envp;
};

void * spe_thread(void * arg)
{
        int flags = 0;
        unsigned int entry = SPE_DEFAULT_ENTRY;
        spe_program_handle_t * program;
        struct thread_args * arg_ptr;

        arg_ptr = (struct thread_args *) arg;

        program = spe_image_open("hello");
        spe_program_load(arg_ptr->ctx, program);
        spe_context_run(arg_ptr->ctx, &entry, flags, arg_ptr->argp,
                        arg_ptr->envp, NULL);
        pthread_exit(NULL);
}

int main() {
        int thread_id;
        pthread_t pts;
        spe_context_ptr_t ctx;
        struct thread_args t_args;
        int value = 1;

        ctx = spe_context_create(0, NULL);

        t_args.ctx = ctx;
        t_args.argp = &value;

        thread_id = pthread_create( &pts, NULL, &spe_thread, &t_args);

        pthread_join (pts, NULL);
        spe_context_destroy (ctx);

        return 0;
}