[vtk-developers] About vtkParametricSpline Initialize() performance

Simon ESNEAULT simon.esneault at gmail.com
Tue Oct 1 04:45:31 EDT 2013


Hi all,

We use a lot vtkParametricSpline here, with quite a lot of points, ~4000
With that number of points, the method "Initialize()" takes around 0.7
seconds (vtk 5.8, linux, intel Core i7 at 3.0 Ghz)

After some hack, this time is reduced to : 0.001 seconds, (700x speed up
!), for the exact same result

Explanations :
While digging into the code, I've noticed that for each added point in
vtkSpline, there is a call of the method SortAndUpdateRange() in
vtkPiecewiseFunction, and after that, a search through all the nodes in
order to return the array index of the point.
Now in vtkParametricSpline, all the point are added with something like :
/********************************************************************/
    for ( len = 0.0, i = 0; i < npts; ++i )
      {
      this->Points->GetPoint(i,x);
      len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev));
  this->XSpline->AddPoint(len,x[0]);
   this->YSpline->AddPoint(len,x[1]);
  this->ZSpline->AddPoint(len,x[2]);
      xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2];
      }
/********************************************************************/

2 remarks :
- we don't need to sort because all the points are added already sorted
(the variable "len" can only increase), or at least we should sort only
once at the end
- we don't use the return value (no need to search)

So I've added a method in vtkSpline which looks like :
/********************************************************************/
void vtkSpline::AddPoints (double* t, double* x, int n)
{
  this->PiecewiseFunction->AddPoints (t, x, n);
}
/********************************************************************/

And another one in vtkPiecewiseFunction which looks like this :
/********************************************************************/
void vtkPiecewiseFunction::AddPoints( double* x, double* y, int n )
{
  for( int i=0; i<n; i++ ){
    vtkPiecewiseFunctionNode *node = new vtkPiecewiseFunctionNode;
    node->X         = x[i];
    node->Y         = y[i];
    node->Sharpness = 0.0;
    node->Midpoint  = 0.5;
    this->Internal->Nodes.push_back(node);
  }
  this->SortAndUpdateRange();
}
/********************************************************************/

Finally the modified vtkParametricSpline Initialize() method looks like :
/********************************************************************/
    double lengths[npts];
    double pointx[npts];
    double pointy[npts];
    double pointz[npts];
    for ( len = 0.0, i = 0; i < npts; ++i )
      {
      this->Points->GetPoint(i,x);
      len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev));
      lengths[i] = len;
      pointx[i] = x[0];
      pointy[i] = x[1];
      pointz[i] = x[2];
      xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2];
      }
    this->XSpline->AddPoints(lengths,pointx,npts);
    this->YSpline->AddPoints(lengths,pointy,npts);
    this->ZSpline->AddPoints(lengths,pointz,npts);
    }
/********************************************************************/

Conclusion :
I know 4000 points for a spline is somewhat stupid, but the gain is
significant and maybe this can help some other people. Also, maybe this can
be useful for TransferFunction with a big number of points. And last but no
least, on windows, the underlying std::sort is especially slow in Debug,
because visual studio enables some heap debugging. So the gain in
performance may even be higher in that case.

Cheers,
Simon


-- 
------------------------------------------------------------------
Simon Esneault
13 rue Vasselot
35000 Rennes, France
Tel : 06 64 61 30 94
Mail : simon.esneault at gmail.com
------------------------------------------------------------------
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtk-developers/attachments/20131001/b93bbe58/attachment.html>


More information about the vtk-developers mailing list