In this post I’d like to introduce Erlpiphany, the Erlang NIF library interface to the Epiphany chip. With this library, the Erlang developer can embed the power of Epiphany-accelerated computing in their application.

Background

I’ve followed the development of Parallella since the announcement of the Kickstarter project, so it was with great excitement that I finally managed to purchase a board. While browsing the user forums, I found a topic devoted to Erlang for the Parallella. Bringing the power of parallel hardware acceleration to Erlang applications seemed to be a worthy community contribution.

The architecture of the Epiphany chip dictated that Erlang would run on the Zynq ARM processors and access the Epiphany cores via the eHAL library. Erlang provides a number of ways to integrate external functions or programs. The NIF (Natively Implemented Functions) library approach was the most straightforward choice. So with an implementation approach chosen and an Erlang API defined, the “Erlpiphany” application was born.

Erlang has features that make it well suited to both quick prototyping and distributed processing. Erlang, the functional language, is part of a larger ecosystem of libraries and a virtual machine (called BEAM), much like Java and the JVM. At one end of the development spectrum, a developer can create fault-tolerant applications that are distributed across multiple nodes and hosts. At the other end of the spectrum, one can write Erlang scripts in much the same fashion as shell scripts.

Scripting

An example of scripting shows the ease at which a developer can access and manage the Epiphany chip and its cores. The Erlang code below uses the Erlpiphany NIF interface to initialize and query the the chip.

#!/usr/bin/env escript

%% -*- erlang -*-

main([]) ->

code:add_path("/home/linaro/Work/erlpiphany"),

code:add_path("/home/linaro/Work/erlpiphany/ebin"),

code:add_path("/home/linaro/Work/erlpiphany/priv"),

application:load(erlpiphany),

ok = ehal:e_init(0),

ok = ehal:e_reset_system(),

{ok, Platform} = ehal:e_get_platform_info(),

io:format("Platform info: ~p~n", [Platform]),

ok = ehal:e_finalize().

This script, when made executable and run by root, will produce the following output

To run the above script as root while logged into the default linaro account, the simple shell script below can provide all the necessary setup.

#!/bin/bash

set -e

ESDK=${EPIPHANY_HOME}

ELIBS=${ESDK}/tools/host/lib:${LD_LIBRARY_PATH}

EHDF=${EPIPHANY_HDF}

sudo -E LD_LIBRARY_PATH=${ELIBS} EPIPHANY_HDF=${EHDF} $*



Large applications, like the various programs found in the epiphany-examples and parallella-examples directories, are best developed as full Erlang modules in the Erlang VM environment. The Erlpiphany application has an examples directory that illustrates how to do this using the hello-world and dotproduct examples.

Once you’ve developed an Epiphany application in Erlang, you can still use the scripting capability of Erlang to run your program without having to launch a full Erlang node. For example, the hello-world directory has an Erlang module named, appropriately enough, hello_world.erl that exports a function main to run the example. Once the module has been compiled to a BEAM file, a script can invoke an exported function in the module just as you would from the Erlang shell.

#!/usr/bin/env escript

%% -*- erlang -*-

main([]) ->

code:add_path("/home/linaro/Work/erlpiphany"),

code:add_path("/home/linaro/Work/erlpiphany/ebin"),

application:load(erlpiphany),

hello_world:main().



Remote Communication

The real power of Erlang lies in its ecosystem, known as Erlang-OTP (Open Telecommunications Platform). Applications can distribute themselves across multiple nodes, fail-over to another node on fault, and communicate transparently between nodes. This capability is too extensive to enumerate in this post, but a few examples can show the advantage of developing Epiphany-accelerated applications in Erlang, particularly with Parallella clusters.

You can log into a remote Erlang node on a Parallella board to run an application you’ve developed. Alternatively, an application on your local node can communicate with remote nodes on Parallella boards to initiate computation and exchange data. Erlang nodes join a cluster when they share a common authorization cookie and are directed to contact other nodes.

An Erlang node can be started from the command line with arguments that define the node name and the cookie value or location (if the cookie is not specified, then the node looks for the file .erlang.cookie in your home directory on startup). The authorization cookie itself is nothing more than a character sequence. The commands below show one way of starting a local node, establishing communication with other nodes, then logging into a remote node.

On the Parallella board…



And on the desktop…



Typing ^G brings up the shell menu and the ‘r’ command can be used to create a shell on the remote Parallella node, as shown with the ‘j’ (jobs) command. You can then connect to the remote shell and issue commands just as if you were logged in locally on the Parallella board, as illustrated by the ls() and pwd() commands.

The nodename@hostname tag in the command prompt helps you keep track of which node you are logged into. Once remotely logged into the Erlang node started on the Parallella board, we can change to the hello-world directory and run the hello world example directly.

The Erlang rpc (remote procedure call) module allows one to invoke Erlang functions without the need for a remote shell. This is one way that a coordinating application on your workstation could spawn processes on one or more Parallella boards. Here for example is how we might invoke the hello_world example program from an Erlang node started in the scripts directory as before.

In the above sequence we connected to the Parallella node in order to change directory to the dotproduct example. After switching back to the local node, the rpc:call command is used to invoke the start function exported by the Erlang dotproduct module. This particular code example spawns a process per Epiphany core, with each process loading and running a program, then sending the result in a message back to the parent process.

A fully developed Erlpiphany application would have a manager process spawning worker processes on remote Parallella nodes. The worker processes would use their Epiphany chip to accelerate computationally intensive parts of the Erlang application, and the manager process would insure workers are restarted if a failure occurs.

This is just a quick tour of Erlang and its capabilities for distributed computation. The Erlpiphany library extends that capability with direct access to the Epiphany chip on your Parallella board. You can find the library on github at the URL

github.com/parallella/pal/tree/master/src/wrappers/erlang

Happy [parallel, distributed] computing!