Getting started

errand is a Python module that enables users to easily use accelerator hardware such as GPU.

errand takes responsibility of data movements between CPU and accelerators like GPU, and creates multiple threads on the accelerators. Therefore, user can focus on computation in well-known programmiong frameworks, such as Cuda, Hip, OpenAcc, and conventional pthread (more programming frameworks are coming.) errand takes advantages of the functionality and convinience of numpy ndarray.

errand makes use of conventional programming tools that you may be already familar with. For example, errand uses Nvidia CUDA compiler or AMD HIP compiler if needed. As of this writing, errand supports CUDA, HIP, OpenAcc(C++), and Pthread(C++).

Installation

The easiest way to install errand is to use the pip python package manager.

>>> pip install errand

You can install errand from github code repository if you want to try the latest version.

>>> git clone https://github.com/grnydawn/errand.git
>>> cd errand
>>> python setup.py install

NumPy array example in CUDA(Nvidia) or HIP(AMD)

To run the example, create two source files in a folder as shown below, and run the Python script as usual. The example assumes that at least one of the following compilers is usable: CUDA (nvcc), HIP(hipcc), C++ OpenAcc(GNU >=10), and Pthread C++ compiler(GNU)).

>>> python main.py

The following Python code demonstrates how to compute numpy arrays using multiple programming frameworks including Cuda, Hip, OpenAcc(GNU), or Pthread(GNU). Errand automatically checks and uses one of frameworks available on the system.

Python code (main.py)

# This example shows how to add numpy arrays using Errand.

import numpy as np
from errand import Errand

N1 = 10
N2 = 20

a = np.ones((N1, N2))
b = np.ones((N1, N2))
c = np.zeros((N1, N2))

# creates an errand context with an "order"
with Errand("order.ord") as erd:

        # build workshop with input(a, b) and output(c)
        workshop = erd.workshop(a, b, "->", c)

        # call N1 teams of N2 gofers
        gofers = erd.gofers(N2, N1)

        # let gofers do their work at the workshop
        gofers.run(workshop)

        # do your work below while gofers are doing their work

# check the result when the errand is completed
if np.array_equal(c, a+b):
        print("SUCCESS!")

else:
        print("FAILURE!")

While Errand handles data movements and thread generation, user needs to specify computation in an order file. For example, the order file below defines an element-wise addition of 2 dimensional array in multiple programming frameworks including Cuda, Hip, OpenAcc-C++, and PThread.

For convinience, Errand provides user with a Numpy ndarray-like interface to the input and output arguments as demonstrated below. For example, an array can be accessed through indices and the shape array is informed with shape member method.

Order code (order.ord)

[cuda, hip]

        // N1 teams are interpreted to Cuda/Hip blocks
        // N2 gofers of a team are interpreted to Cuda/Hip threads

        int row = blockIdx.x;
        int col = threadIdx.x;

        // the input and output variables keep the convinience of numpy

        if (row < x.shape(0) && col < x.shape(1))
                c(row, col) = a(row, col) + b(row, col);

[openacc-c++]

        #pragma acc loop gang
        for (int row = 0; row < a.shape(0); row++) {

                #pragma acc loop worker
                for (int col = 0; col < a.shape(1); col++) {
                        c(row, col) = a(row, col) + b(row, col);
                }
        }

[pthread]

        int row = a.unravel_index(ERRAND_GOFER_ID, 0);
        int col = a.unravel_index(ERRAND_GOFER_ID, 1);

        if (row < a.shape(0) && col < a.shape(1) )
                c(row, col) = a(row, col) + b(row, col);