SkePU

Autotunable Multi-Backend Skeleton Programming Framework for Multicore CPU and Multi-GPU Systems

FAQ Overview Download Publications Code Example Applications Features License Ongoing Work Contact Acknowledgments

Further Example Programs

The following code snippets are excerpted from full source codes that can be found in the examples directory of the public SkePU release.



Vector Reversal / Permutation / Scatter using the MapArray Skeleton

The following code snippet is a simple example for using the MapArray skeleton: Reversing a 1D array. Permuting or scattering an array can be done in the same way.
The first argument (v0) of the MapArray is the fully accessible read-only operand, here the array to be permuted.
The second argument (v1) is the elementwise-accessed operand, here the permutation vector. It is used to elementwise fill the result vector r with the desired elements from v0.
#include "skepu/vector.h"
#include "skepu/maparray.h"

ARRAY_FUNC( scatter_f,  float,  a, b_i,
            int index = (int) b_i;
            return a[index];
          )

int main()
{
   skepu::MapArray < scatter_f > reverse( new scatter_f );

   skepu::Vector<float> v0(10);
   skepu::Vector<float> v1(10);

   skepu::Vector<float> r;

   // Sets v0 = 1 2 3 4 5...     (data array)
   //      v1 = 19 18 17 16...   (index array)
   for (int i = 0; i < 10; ++i) {
      v0[i] = (float)(i+1);
      v1[i] = (float)(10-i-1);
   }

   reverse( v0, v1, r );

   std::cout << "r: " << r << "\n";
   return 0;
}


Dense Matrix-Vector Multiply

An important use case of the MapArray skeleton is Matrix-Vector multiply.
The first of the two MapArray input arguments (v0) is the vector operand to be made fully accessible to every elementary computation of the result operand (r).
The second MapArray argument, here a Matrix container (m1), is accessed elementwise by the user function; here this means row-wise access to the matrix rows because the elementwise accessed output data is just a vector here (r).
#include "skepu/maparray.h"
#include "skepu/vector.h"
#include "skepu/matrix.h"

#define SIZE 100

/* User function specification: a scalar dot product
 */
ARRAY_FUNC_MATR_BLOCK_WISE( sdot,  float,  b, a_i, SIZE,
                            float res_i = 0;
                            for (int j=0; j<100; ++j) {
                               res_i += a_i[j] * b[j];
                            }
                            return res_i;
                          )

int main()
{
   skepu::MapArray< sdot > MatVecMult( new sdot );

   skepu::Vector< float> v0(SIZE);
   skepu::Matrix< float> m1(SIZE,SIZE);
   skepu::Vector< float> r(SIZE);

   // ... set values of m, v0

   MatVecMult( v0, m1, r );

   // ...
}


Sparse Matrix-Vector Multiply

(... TBD ...)


2D Convolution (2D Stencil Computation)

#include "skepu/matrix.h"
#include "skepu/mapoverlap.h"

// some row/column size definitions....
#define INNER_ROWS 16
#define INNER_COLS 10
#define OVERLAP_ROWS 2 // max. access distance along vertical axis
#define OVERLAP_COLS 1 // max. access distance along horizontal axis
#define ALL_ROWS (INNER_ROWS + OVERLAP_ROWS*2)
#define ALL_COLS (INNER_COLS + OVERLAP_COLS*2)

/* User-function definition:
 *   here, an irregular 9-point stencil with unit weights.
 * For 2D-convolution we use macro "OVERLAP_FUNC_2D_STR".
 * Parameters are:
 *   name, datatype, overlap length on horizontal axis,
 *   overlap length on vertical axis, name of parameter,
 *   the stride which is used to access items column-wise,
 *   and the actual function body.
 */
OVERLAP_FUNC_2D_STR( stencil,  int,  OVERLAP_COLS, OVERLAP_ROWS,  a, stride,
                     return ( a[-2*stride-1] + a[-1*stride+1] + a[-1*stride]
                            + a[-1] + a[0] + a[1]
                            + a[1*stride+1] + a[2*stride] + a[2*stride+1] );
                   )

int main()
{
   skepu::MapOverlap2D< stencil > mat_conv( new stencil );

   skepu::Matrix m0( ALL_ROWS, ALL_COLS,  -1);
   skepu::Matrix m1( INNER_ROWS, INNER_COLS,  0);

   // initializing inner elements of input matrix:

   // ... (could use the Generate skeleton for this)

   std::cout << "Input " << m0 << "\n";

   // Applying 2D convolution in-place:
   mat_conv( m0 );

   // Applying 2D convolution on m0 again, inner elements written to m1:
   mat_conv( m0, m1 );

   std::cout << "Output " << m1 << "\n";  return 0;
}
There is also the possibility to specify a filter weight matrix as an optional third operand, here for a 3x3 stencil:
// ...
   skepu::Matrix m_weights(3,3);  // 3x3 filter weight matrix
// ...
   skepu::MapOverlap2D< stencil33 > mat_conv( new stencil33 );
// ... set m_weights = [1, 2, 1, 2, 4, 2, 1, 2, 1]
// ...
   conv2D( m0, m1, m_weights );
// ...


... TO BE CONTINUED ...



Back to the SkePU homepage