Jump to content

Replacing rows in a 2D array is significantly faster than replacing columns


Recommended Posts

I guess it is expected if you think about how the arrays are laid out in memory, but still interesting to confirm.

For the eagle eyed I know my two loops will not actually produce the same result, but I don't think this should change the conclusion.

 

Screenshot 2021-05-11 213658.png

Link to comment
21 minutes ago, Neil Pate said:

I guess it is expected if you think about how the arrays are laid out in memory, but still interesting to confirm.

Maybe then you will find that VI interesting as well. I made that to compare different methods to replace rows/columns in the array (four known at the moment).

Link to comment
1 hour ago, dadreamer said:

Maybe then you will find that VI interesting as well. I made that to compare different methods to replace rows/columns in the array (four known at the moment).

Risky click of the day running that VI!

But hey, life is short so I tried. My Russian is a bit rusty but I guess you came to a similar conclusion?

Link to comment
1 hour ago, Darren said:

Do you see similar results when running the benchmarks separately, i.e. one at a time in separate VIs as opposed to in parallel in the same VI?

Yes I did. Actually my first benchmark was just to make the change manually in the VI and re-run it. The results are the same.

Sorry my picture was not good, if you look closely I introduce some forced data flow from the first structure to the second so that they do not run in parallel as I did not want to bias the results in any way.

Link to comment
10 hours ago, Neil Pate said:

My Russian is a bit rusty but I guess you came to a similar conclusion?

Yeah, I guess it's obvious for (almost) every programmer. And well illustrated by the 4th method with MoveBlock call. Looking at that one might say, this is how the replace operation is made internally.

 

By the way it's possible to speed up MoveBlock method a little disabling the wrapper generation. But still it is inferior in speed to the native methods (i.e., Replace Array Subset and In Place Element Structure).

Edited by dadreamer
Link to comment
11 hours ago, dadreamer said:

Yeah, I guess it's obvious for (almost) every programmer. And well illustrated by the 4th method with MoveBlock call. Looking at that one might say, this is how the replace operation is made internally.

 

By the way it's possible to speed up MoveBlock method a little disabling the wrapper generation. But still it is inferior in speed to the native methods (i.e., Replace Array Subset and In Place Element Structure).

I actually have a scenario where your MoveBlock method might be faster. Using the primitives you cannot replace a portion of a row (which is actually what I want to do). This should be a lightning fast operation but I have to either do it item by item or index out the row first, replace a portion of it and then replace the 2D array.

My code might be sped up a bit with an In Place structure, I have not yet tried this.

Method 1.png

Method 2.png

Link to comment
3 hours ago, Neil Pate said:

I actually have a scenario where your MoveBlock method might be faster. Using the primitives you cannot replace a portion of a row (which is actually what I want to do). This should be a lightning fast operation but I have to either do it item by item or index out the row first, replace a portion of it and then replace the 2D array.

Probably slower than your method, but it is possible using primitives, and it is quite messy also. See below.

 

Snip.png.abde3e413c2e737ff0550dc25ef8068d.png

Link to comment

Only when I disable the wrapper generation on the CLFN, I see some small performance gain in MoveBlock against Replace Array Subset:

2021-05-13_11-44-58.jpg.c9adabc49677de15c36ee527cb010459.jpg

So, in all other use-cases the native nodes do their job just fine and they're much simplier to use (and more safe also). That is just a PoC method to show, that the work with arrays could be done "traditional way" in LabVIEW too as in text-based languages. I even suppose, Replace Array Subset and In Place Element Structure were both optimised/tweaked in some ways to behave better even in a dumb memory copying.

Link to comment
2 hours ago, dadreamer said:

Only when I disable the wrapper generation on the CLFN, I see some small performance gain in MoveBlock against Replace Array Subset:

2021-05-13_11-44-58.jpg.c9adabc49677de15c36ee527cb010459.jpg

So, in all other use-cases the native nodes do their job just fine and they're much simplier to use (and more safe also). That is just a PoC method to show, that the work with arrays could be done "traditional way" in LabVIEW too as in text-based languages. I even suppose, Replace Array Subset and In Place Element Structure were both optimised/tweaked in some ways to behave better even in a dumb memory copying.

Sure, but I am surprised that looping over an array doing individual array element replaces is quicker than doing a single MoveBlock! Seems suspicious...

Link to comment

I did a test like yours with For Loop and MoveBlock is a bit faster here. I'm getting 0,03 ms for RAS and 0,01 ms for MB.

2021-05-13_17-54-23.jpg.c3d2f1d396bd7e45dcfe8ad32b17851e.jpg

2021-05-13_17-55-52.jpg.d0110d581f08ac12eef2dca3bc09192d.jpg

I took Initialize Array on MB diagram out of the Sequence, because it's just an extra operation. Also make sure you are not timing and filling the output indicator simultaneously, because the latter vastly impacts the measurements.

Edited by dadreamer
Link to comment
1 hour ago, dadreamer said:

I did a test like yours with For Loop and MoveBlock is a bit faster here. I'm getting 0,03 ms for RAS and 0,01 ms for MB.

2021-05-13_17-54-23.jpg.c3d2f1d396bd7e45dcfe8ad32b17851e.jpg

2021-05-13_17-55-52.jpg.d0110d581f08ac12eef2dca3bc09192d.jpg

I took Initialize Array on MB diagram out of the Sequence, because it's just an extra operation. Also make sure you are not timing and filling the output indicator simultaneously, because the latter vastly impacts the measurements.

It really makes sense to me to have the MoveBlock be the fastest when replacing a row (or subset of a row). I wonder if the difference is also more exteme as the size of the replacement changes? In other words replacing a section 1M elements long is probably much slower when doing it element by element compared to a single MoveBlock call.

Link to comment
3 hours ago, Neil Pate said:

I wonder if the difference is also more exteme as the size of the replacement changes? In other words replacing a section 1M elements long is probably much slower when doing it element by element compared to a single MoveBlock call.

It doesn't seem so. For a row of 1048576 bytes it takes ~4 ms for RAS and ~3 ms for MB. Not a huge difference.

Link to comment
On 5/13/2021 at 8:36 PM, Phillip Brooks said:

What is the overhead of using Transpose 2D array?

https://zone.ni.com/reference/en-XX/help/371361R-01/glang/transpose_2d_array/

Might transpose -> replace -> transpose be an option?

Not likely. The efficiency in the Transpose function comes from the fact that LabVIEW really creates something that is called a sub array. This is not a real array but a data structure that contains flags, offset, stride and similar attributes and a pointer to the original array data. Many functions in LabVIEW are able to operate on both arrays and sub arrays. A transposed array simply stores the fact that the array data is actually transposed in the flags and then any function that sees it knows to exchange the row and column value in the original array. If a function doesn't support the sub array flavor it simply calls a function that converts the sub array into a real array, eventually imposing the penalty of the transpose operation anyhow, but many functions can simply work with such sub arrays directly.

A graph for instance has the ability to transpose the 2D array data already, so if it receives a transposed sub array it simply inverts the transpose setting of the graph for this array data.

For the indexing into the array the fact that the array is transposed should not really make a big difference as the real data is still in the original order (if it wasn't, the whole operation would not only use double the memory but be significantly slower as shuffling the data around is taking some performance).

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.