About VSIPL++

application/pdf Data Sheet
application/pdf Building Signal-Processing Applications for the Cell Broadband Engine
text/html Evaluation Request

Manuals

text/html Quickstart
application/pdf Quickstart
text/html Tutorial
application/pdf Tutorial
application/pdf VSIPL++ API Specification (Serial)
application/pdf VSIPL++ API Specification (Parallel)
text/html API Reference

Mailing Lists

icon Announcements
icon Development

Comparing Sourcery VSIPL++ to VSIPL

Sourcery VSIPL++ provides substantial productivity advantages relative to the VSIPL API. Using Sourcery VSIPL++, you will write only one third as much code to implement typical signal-processing algorithms. (While this page is focused on the productivity advantages, using Sourcery VSIPL++ has other advantages too: it is much easier to make your application run in parallel, and, in some cases, you will get superior performance.)

This page provides implementations of "pulse-compression" (a building block of many signal-processing algorithms) using Sourcery VSIPL++ and the VSIPL API. Pulse compression consists of three steps. First, an FFT is applied to transform time-domain data into frequency-domain data. Then, a vector-matrix multiply is performed in the frequency domain. Finally, an inverse FFT is applied to return to the time domain.

Sourcery VSIPL++ Implementation

With Sourcery VSIPL++, the entire algorithm can be expressed in just seven statements: three set-up statements, two statements to declare the forward and inverse FFTs, and two to perform the actual computation.

template <typename View1, typename View2, typename View3>
void pulseCompression(int decimationFactor, 
                      View1 in, View2 ref, View3 out) {
  int size = in.size() / decimationFactor;
  Domain<1> decimatedDomain(0, decimationFactor, size);
  Vector tmp(size);

  Fft<Vector, typename View1::value_type, 
      typename View2::value_type, fft_fwd> 
    forwardFft (size, 1);
  Fft<Vector, typename View2::value_type, 
      typename View3::value_type, fft_inv, by_reference> 
    inverseFft (size, 1.0/size);
  tmp = ref * forwardFft(in(decimatedDomain));
  inverseFft(tmp, out);
}

VSIPL API Implementation

The VSIPL implementation of the same algorithm requires nineteen statements — three times that required for the Sourcery VSIPL++ implementation. The VSIPL++ API allows the user to write the core computation in fewer statements than VSIPL. And, VSIPL++ requires many fewer statements because the VSIPL++ API supports automatic memory allocation. (Of course, you can still control memory allocation manually if necessary.)

void pulseCompression(int decimationFactor,
                      vsip_cvview_f *in, 
                      vsip_cvview_f *ref, 
                      vsip_cvview_f *out) {
  vsip_length savedSize   = vsip_cvgetlength_f(in);
  vsip_length savedStride = vsip_cvgetstride_f(in);

  vsip_length size = vsip_cvgetlength_f(in) / decimationFactor;

  vsip_fft_f *forwardFft = 
    vsip_ccfftop_create_f(size, 1.0, VSIP_FFT_FWD, 1, 
                          VSIP_ALG_SPACE);
  vsip_fft_f *inverseFft =
    vsip_ccfftop_create_f(size, 1.0/size, VSIP_FFT_INV, 1, 
                          VSIP_ALG_SPACE);

  vsip_cvview_f *tmpView1 = vsip_cvcreate_f(size, VSIP_MEM_NONE);
  vsip_cvview_f *tmpView2 = vsip_cvcreate_f(size, VSIP_MEM_NONE);

  if (forwardFft && inverseFft && tmpView1 && tmpView2) {
    vsip_cvputlength_f(in, size);
    vsip_cvputstride_f(in, decimationFactor);

    vsip_ccfftop_f(forwardFft, in, tmpView1);
    vsip_cvmul_f(tmpView1, ref, tmpView2);
    vsip_ccfftop_f(inverseFft, tmpView2, out);

    vsip_cvputlength_f(in, savedSize);
    vsip_cvputstride_f(in, savedStride);
  }

  if (tmpView1)   vsip_cvalldestroy_f(tmpView1);
  if (tmpView2)   vsip_cvalldestroy_f(tmpView2);
  if (forwardFft) vsip_fft_destroy_f(forwardFft);
  if (inverseFft) vsip_fft_destroy_f(inverseFft);
}

Working with Multiple Precisions

The Sourcery VSIPL++ implementation has a further productivity advantage that is not obvious from the examples above. Suppose that you want to perform pulse-compression on both single-precision and double-precision data. Or, suppose that you want to experiment with using different precisions to see how they affect accurancy and performance.

To modify the single-precision VSIPL code shown above to use double-precision, you must change the suffixes of the functions used from _f to _d. This change is simple in concept, but time-consuming and error-prone. And, you may need to maintain both routines for the life of your application.

In Sourcery VSIPL++, no change to the code is required, due to the use of C++ templates. The same function can be used whether in, out, and ref are single-precision or double-precision matrices. There's nothing to change, and you only need to maintain one copy of the algorithm.