Getting started: The Basics

EBSP programs are written in SPMD (single-program multiple-data) style. This means that each core runs the same code, but obtains different data. Later we will see how we can transfer data to and from the Epiphany cores, but for now our first step will be to get the cores to output their designated core number (called pid for processor identifier). Like all programs written for the Parallella, an EBSP program consists of two parts. One part contains the code that runs on the host processor, the ARM chip that hosts the Linux OS. The other part contains the code that runs on each Epiphany core. In heterogeneous computing it is common to call this second part the kernel.

Hello World!

A host program consists of at least four EBSP functions, which are generally used as in the following example::

// file: host_code.c

#include <host_bsp.h>

int main(int argc, char **argv)
{
    bsp_init("ecore_program.srec", argc, argv);
    bsp_begin(16);
    ebsp_spmd();
    bsp_end();

    return 0;
}

The first call to bsp_init initializes the EBSP library. The first argument is the filename of the (compiled) kernel program, and the second and third arguments are the program arguments. Next we tell the EBSP system how many cores we would like to use (in this case; all 16 cores for a standard Parallella board) by calling bsp_begin passing 16 as its first argument. The call to ebsp_spmd starts the execution of the kernel program on the 16 cores. When the execution has finished we finalize the EBSP system by calling bsp_end without arguments.

Next we write the kernel for our Hello World program. Besides outputting “Hello World” we also show the processor number. The code looks like this::

// file: ecore_code.c

#include <e_bsp.h>

int main()
{
    bsp_begin();
    int s = bsp_pid();
    int p = bsp_nprocs();
    ebsp_message("Hello World from processor %d / %d", s, p);
    bsp_end();

    return 0;
}

Let us also go over the kernel code line by line. First we initialize the EBSP system on the core, by calling bsp_begin. In a kernel program this call does not require any arguments, since there is no additional program to run! Next we obtain information about our own designated processor number (commonly called s) using bsp_pid, and the total number of processors (commonly called p) by calling bsp_nprocs. We then output a message to host using ebsp_message. This function can be used completely identically to printf in ordinary C programs. Again we finalize the system with a call to bsp_end which cleans up the EBSP system.

You may have noticed that some EBSP functions, which we will refer to as primitives, are prefixed with bsp_ while others are prefixed by ebsp_. This is because the EBSP library introduces some functions that are not in the BSPlib standard but that can be very helpful when programming for the Epiphany.

Running this program should result in output similar to the following::

$08: Hello World from processor 8 / 16
$01: Hello World from processor 1 / 16
$07: Hello World from processor 7 / 16
$02: Hello World from processor 2 / 16
$15: Hello World from processor 15 / 16
$03: Hello World from processor 3 / 16
$10: Hello World from processor 10 / 16
$06: Hello World from processor 6 / 16
$12: Hello World from processor 12 / 16
$13: Hello World from processor 13 / 16
$05: Hello World from processor 5 / 16
$04: Hello World from processor 4 / 16
$11: Hello World from processor 11 / 16
$14: Hello World from processor 14 / 16
$09: Hello World from processor 9 / 16
$00: Hello World from processor 0 / 16

The output has the form $[pid]: output. As we see, indeed the EBSP kernel is being run on every core! Note that there are no guarantees about which core gets to the ebsp_message statement first, and therefore the output need not be in order of processor number.

Interface (Basics)

Host

int bsp_init(const char *e_name, int argc, char **argv)

Initializes the BSP system.

Sets up all the BSP variables and loads the epiphany BSP program.

Return
1 on success, 0 on failure
Parameters
  • e_name: A string with the srec binary name of the Epiphany program
  • argc: The number of input arguments
  • argv: An array of strings with the input arguments

The string e_name must be of the form myprogram.srec. This function will search for the file in the same directory as the host program, and not in the current working directory.

Usage example:

int main(int argc, char** argv)
{
    bsp_init("e_program.srec", argc, argv);
    ...
    return 0;
}

Remark
The argc and argv parameters are ignored in the current implementation.

int bsp_begin(int nprocs)

Loads the BSP program onto the Epiphany cores.

Usage example:

int main(int argc, char** argv)
{
    bsp_init("e_program.srec", argc, argv);
    bsp_begin(bsp_nprocs());
    ...
    return 0;
}
Return
1 on success, 0 on failure
Parameters
  • nprocs: The number of processors to run on

Remark
The current implementation only allows nprocs to be a multiple of 4 on the 16-core Parallella. Other values of nprocs are rounded down.

int ebsp_spmd()

Runs the Epiphany program on the Epiphany cores.

This function will block until the BSP kernel program is finished.

Return
1 on success, 0 on failure (e.g. after bsp_abort is called on a core)

int bsp_end()

Finalizes and cleans up the BSP program.

Usage example:

int main(int argc, char** argv)
{
    bsp_init("e_program.srec", argc, argv);
    bsp_begin(bsp_nprocs());
    ebsp_spmd();
    bsp_end();
    return 0;
}
Return
1 on success, 0 on failure

Remark
This function is different from the bsp_end function in e_bsp.h

Epiphany

void bsp_begin()

Denotes the start of a BSP program.

This initializes the BSP system on the core.

Must be called before calling any other BSP function. Should only be called once in a program.

int bsp_pid()

Obtain the processor identifier of the local core.

Return
An integer with the id of the core The processor id is an integer in the range [0, .., bsp_nprocs() - 1].

int bsp_nprocs()

Obtain the number of Epiphany cores currently in use.

Return
An integer indicating the number of cores on which the program runs.

void bsp_end()

Denotes the end of a BSP program.

Finalizes and cleans up the BSP program. No other BSP functions are allowed to be called after this function is called.

Remark
Must be followed by a return statement in your main function if you want to call ebsp_spmd() multiple times.

void ebsp_message(const char *format, ...)

Output a debug message printf style.

ebsp_message() outputs a debug message by sending it to shared memory So that the host processor can output it to the terminal The attributes in this definition make sure that the compiler checks the arguments for errors.

Parameters
  • format: The formatting string in printf style