MatrixOp speed issue with SetRow

I am trying to speed up a function that includes a for-loop that stores a 1D wave in a certain row of a 2D wave. The original code used wave assignments (i.e. matrix[0][] = wave[q]). This worked fine, but I figured I could speed it up using MatrixOp. However, when I replaced that line with MatrixOp, using the SetRow option, it was about 100 times slower.

I wrote some code to demonstrate this problem. In this code, I first compared methods for pulling a row out of a 2D wave and found that, as expected, MatrixOp is faster. Then I compared methods for inserting a row into a 2D wave and found MatrixOp was much slower.

Function myFunction()
   
    Variable vStartTimer, vStopTimer, iDex
    Make/O/N=(2000,2048) mMatrix = p + sqrt(q) 
    Make/O/N=(1,2048) mSubMatrix
   
    //First, pull each row out of mMatrix and store in mSubMatrix
    Printf "\rPart I: pull out a row\r"
   
    //Using wave assignements
    vStartTimer = StartMSTimer
    For(iDex = 0; iDex < 2000; iDex += 1)
        mSubMatrix = mMatrix[iDex][q]
    EndFor
    vStopTimer = StopMSTimer(vStartTimer)
    Printf "Time = %g sec (using wave assignments)\r", vStopTimer / 1000000

    //Using MatrixOp
    vStartTimer = StartMSTimer
    For(iDex = 0; iDex < 2000; iDex += 1)
        MatrixOp/O mSubMatrix = Row(mMatrix,iDex)
    EndFor
    vStopTimer = StopMSTimer(vStartTimer)
    Printf "Time = %g sec (using MatrixOp)\r", vStopTimer / 1000000
   
    //Second, insert mSubMatrix into mMatrix for each row
    Printf "\rPart II: insert a row\r"
   
    //Using wave assignemtns
    vStartTimer = StartMSTimer
    For(iDex = 0; iDex < 2000; iDex += 1)
        mSubMatrix = iDex + sqrt(q)
        mMatrix[iDex][] = mSubMatrix[0][q]
    EndFor
    vStopTimer = StopMSTimer(vStartTimer)
    Printf "Time = %g sec (using wave assignments)\r", vStopTimer / 1000000

    //Using MatrixOp
    vStartTimer = StartMSTimer
    For(iDex = 0; iDex < 2000; iDex += 1)
        mSubMatrix = iDex + sqrt(q)
        MatrixOp/O mMatrix = SetRow(mMatrix,iDex, mSubMatrix)
    EndFor
    vStopTimer = StopMSTimer(vStartTimer)
    Printf "Time = %g sec (using MatrixOp)\r", vStopTimer / 1000000    
   
End

The result I get is:

•myFunction()
  
Part I: pull out a row
  Time = 0.182665 sec (using wave assignments)
  Time = 0.110626 sec (using MatrixOp)
  
Part II: insert a row
  Time = 0.287957 sec (using wave assignments)
  Time = 38.3542 sec (using MatrixOp)

What am I missing here? Is MatrixOp slower than wave assignments for some functions?

I am using Igor 7.0.8.1 with Windows 10, but I also had a colleague try it on Igor 8 with a Mac and he got a similar result.

Thanks for any advice you've got!

Almost all of the time spent in MatrixOp in this example is copying the data. Unlike with the wave assignment statement, MatrixOp doesn't operate directly on the original input wave.

Given a sufficient number of processor cores, there are many cases where a MultiThread wave assignment statement can significantly outperform MatrixOp. But of course there are many cases, particularly with complicated expressions, where MatrixOp is the best approach.

I think that the main part that you are missing is the optimal usage of MatrixOP.  In this case, you want to eliminate the loop completely and you will find significant speed enhancement:

 

// mMatrix=p+sqrt(q) translated to MatrixOP:
MatrixOp/O mMatrix=indexRows(mMatrix)+sqrt(indexCols(mMatrix))

 

Forum

Support

Gallery

Igor Pro 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More