Optimizing a Single Function

From OpenCV on the Cell

Jump to: navigation, search

The page explains instructions to add a new function to CVCell module. If you want to optimize new OpenCV functions, read this page and try it.

Contents

Setup build environment

Setup build environment, get source, extract source and create followed directory tree:

|-- opencv-1.0.0  <---- opencv-1.0.0-cell-patch is applied.
|    |-- cv
|    |-- cxcore
|    |-- cvaux
|    `-- ...
|
|
`-- cvcell
     |-- scripts
     |    `-- make_template.rb  <---- The script which adds a function automatically
     `-- src
          |-- ppu
          `-- spu

To create the directory tree, execute following commands:

$ wget http://downloads.sourceforge.net/opencvlibrary/opencv-1.0.0.tar.gz?modtime=1162852454&big_mirror=1
$ wget http://downloads.sourceforge.net/cvcell/cvcell-0.1.0-20071009.tar.gz?modtime=1191964498&big_mirror=0
$ wget http://downloads.sourceforge.net/cvcell/opencv-1.0.0-cell-patch-20071009.tar.gz?modtime=1191964515&big_mirror=0
$ tar -zxf cvcell-0.1.0-20071009.tar.gz 
$ tar -zxf opencv-1.0.0-cell-patch-20071009.tar.gz
$ tar -zxf opencv-1.0.0.tar.gz
$ (cd opencv-1.0.0; patch -p1 < ../opencv-1.0.0-cell-patch-20071009/opencv-cell.patch)


To get more information, please see Installation page.

Make a template

The file named make_template.rb is a script which generates files necessary to optimize a function from the automatic operation as follows. When you optimize a function, you can skip some of tasks that is explained on since the following section by using the script.

  1. Update a function declaration.
  2. Add a function name to a module entry in _*cell header that is corresponds a module that contains a target function.
  3. Add the file name that contains a function to cvcell/src/spu/Makefile and cvcell/src/ppu/Makefile.
  4. Add the name of the function code that is corresponds the function name to FuncCode in cvfunc.h .
  5. Create a template file that contains an entry point of the target function.
  6. Copy the original code to cvcell/src/ppu.

When the execution of this script ends, please advance to the processing that modifies PPE program and creates SPE program. It is necessary to build the CVCell module at the end.

Update a function declaration

The CVCcell module is implemented as a module of the OpenCV library. Please see OpenCV plugin module.

Modify a function declaration

Modify a function declaration to insert hook of the module invocation as follows:

Before:

CV_IMPL void
cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
{
   ...

After:

IPCVAPI_IMPL( void,
              cvCvtColor,
              ( const CvArr* srcarr, CvArr* dstarr, int code ),
              ( srcarr, dstarr, code) )
{
   ...

Register a name of a function

Please register a function into a list of function name to notice the external module. The list of the name that is corresponded the additional function exists in the header file in the same directory that contains the target function. Refer to find the file name that is corresponding to the function to the following:

Directory containing source file Corresponding header file
opencv-1.0.0/cv/src opencv-1.0.0/cv/src/_cvcell.h
opencv-1.0.0/cxcore/src opencv-1.0.0/cxcore/src/_cxcell.h
opencv-1.0.0/cvaux/src opencv-1.0.0/cvaux/src/_cvauxcell.h


Example:_cvcell.h

#ifndef _CV_CELL_H_
#define _CV_CELL_H_

IPCVAPI_EX( void,                                              // Type
            cvCvtColor,                                        // Function name
            "cvCvtColor",                                      // Function name string
            CV_PLUGINS1(CV_PLUGIN_CELLCV),                     // not care
            ( const CvArr* srcarr, CvArr* dstarr, int code )   // Argument declaration
          )
                  .
                  .
                  .

#endif /*_CV_CELL_H_*/

Build the OpenCV Library

Build and install the OpenCV library as follows:

$ cd opencv-1.0.0
$ ./configure
$ make
# make install

Modify the CVCell module to optimize a function

The CVCell module is a shared library. The created function is contained in libcvcell.so and called from an OpenCV library. The SPU program is executed using SPU Code Overlay.


Determine the function name

Determine the function name and the file name as follows. The enum value is used in order to call the function on SPU program from PPU.

Target function name PPU file name enum value SPU file name SPU function name
cvCvtColor cvcolor.cpp CV_CVTCOLOR cvCvtColor_spu.cpp cvCvtColor_spu
cvRandArr cxrand.cpp CV_RANDARR cvRandArr_spu.cpp cvRandArr_spu


Note: Make the same SPU file name and SPU function name. It is used when creating function label from the SPU file name in Makefile.


Modify the src/ppu/Makefile.am

Add the PPU file name to SRCS.

#
# PPU libraries
#
SRCS = ppubase.cpp speconsumer.c cvcolor.cpp cxrand.cpp

Modify the src/spu/Makefile.am

Add the SPU file name to SEGMENT_SRCS.

#
# Segment programs
#
SEGMENT_SRCS = cvRandArr_spu.cpp cvCvtColor_spu.cpp

Add other required source files to LIB_SRCS. It is usually SPU optimized code. When you want to link the original source code in spu/org directory, it is not necessary to add here.

#
# libraries
#
LIB_SRCS = dma.cpp cxerror.cpp cvcolor.cpp

Modify the include/cvfunc.h

Add the SPU function declaration and enum value for calling from PPU.


typedef enum {
    CV_CVTCOLOR,
    CV_RANDARR,
} FuncCode;

#ifdef __SPU__

int cvCvtColor_spu(void);
int cvRandArr_spu(void);

#endif //__SPU__

Modify a PPU program

To pass parameter to SPU and to call SPU program, create the PPU program or modify original source code with a reference to following: The spe-allocator is used in order to call the SPU program from PPU. Define the parameter structure to include/apiparam.h.

#include "spe-allocator.h"
#include "apiparam.h"
#include "ppubase.h"

static void
icvCvtColor_spe( const CvArr* srcarr, CvArr* dstarr, int code)
{
    SpeAllocatorResult spes[cvCellSpeAllocator.max_num];
    param_cvCvtColor *param;

    CvMat *src, *dst;
    int i, ret, remain, height, h;

    int spenum = speAllocatorAllocSpeMax( &cvCellSpeAllocator, spes );
    unsigned int func_code = CV_CVTCOLOR;
    for (i = 0; i < spenum; i++) {
        /* start cvtcolor */
        spe_in_mbox_write( spes[i].spe, &func_code, 1, SPE_MBOX_ALL_BLOCKING );
    }

    param = (param_cvCvtColor*)memalign( 128, sizeof(param_cvCvtColor) * spenum );

    src = cvGetMat( srcarr, &srcstub );
    dst = cvGetMat( dstarr, &dststub );
    h = src->rows;

    remain = h % spenum;
    height = h / spenum;

    for (i = 0; i < spenum; i++) {
        param[i].srcmat = src;
        param[i].dstmat = dst;
        param[i].code   = code;
        // option
        param[i].height = height + ((i==spenum-1)?remain:0);
        param[i].start_y = height * i;
        mbox_write_addr( spes[i].spe, &param[i], SPE_MBOX_ALL_BLOCKING );
    }

    // recieve 32bit return code 
    for (i = 0; i <spenum; i++) {
        unsigned int v;
        spe_out_intr_mbox_read( spes[i].spe, &v, 1, SPE_MBOX_ALL_BLOCKING );
    }

    free( param );
    speAllocatorFreeSpe( &cvCellSpeAllocator, spenum, spes );
}

CV_IMPL void
cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
{
    ...
    if( spenum > 0 )
    {
        // 16byte align
        IplImage src = *(IplImage*)srcarr;
        IplImage dst = *(IplImage*)dstarr;
        icvCvtColor_spe( (CvArr*)&src, (CvArr*)&dst, code);
        return;
    }
    ...

Add a case statement

Add the code for branching to the SPU function. main of SPE exists in src/spu/spumain.cpp .

int
main(unsigned long long spe, unsigned long long argp, unsigned long long envp)
{

    while( 1 )
    {
        FuncCode func = (FuncCode)spu_read_in_mbox();
        switch(func)
        {
        case CV_CVTCOLOR:
            cvCvtColor_spu();
            break;
        case CV_RANDARR:
            cvRandArr_spu();
            break;
        case ...

       }

    }
    return 0;
}

Create a SPE program

Create the SPU program. The SPU program is created without startup routine for SPU code overlay. Therefore, it must call CLEAR_BSS macro first. It clears .bss section by zero instead of startup routine.

extern "C" innt cvCvtColor_spu(unsigned int buff, unsigned int size)
{
    CLEAR_BSS;

    // get API param
    param_addr = mbox_read_effective_addr();
    mfc_get( &param, param_addr, sizeof(param), 0, 0, 0 );
    mfc_write_tag_mask( 1 );
    mfc_read_tag_status_all();
    ...


On the CVCcell of latest svn HEAD version don't need CLEAR_BSS, clearing bss code is moved to spumain.cpp.

Build the CVCell module

Build as follows:

$ cd cvcell
$ autoreconf
$ ./configure
$ make
Views
Personal tools
Toolbox