Test and Measurement Forum

Streaming example code and LV memory management

Post your LabVIEW discussions here

Streaming example code and LV memory management

Postby dmsilev » Fri May 12, 2017 5:52 pm

I was working to get the PicoScope streaming code running on my system, and after spending some time studying the code and then talking with some LabView mavens, I realized that there's a potential issue with how the examples are written which could cause the code to fail sometime in the future if NI changes how it internally implements some features. The good news is that it's straightforward to rewrite in a safer manner.

The essence of the issue is that the supplied example code makes an unwarranted assumption about how LV manages memory. It assumes that for a LV native array, once that array is generated it will remain in the same location in memory and that a pointer to that memory block which is valid when the array is generated will remain valid throughout the runtime. That's fundamentally how the example code for streaming works:
picoscope snippet.png

Inside the Start Stream subVI, some 1D I16 arrays are generated and are passed to the SDK DLLs as pointers, and then the array is outputted to the top-level VI. The DLLs then do in-place overwriting of the data inside that array, and the Array Subset routine is used to pull out the newest set of data. The only way that this works is if the array doesn't move in memory from when it's created in the subroutine to when it's passed to the upper routine and then throughout the running of the loop. That's the case now, but it's not guaranteed (NI black-boxes their memory management), and if it changes we'd be looking at memory access exceptions and other fun issues.

So, a better approach is to do manual memory management, and explicitly generate pointers to static blocks of memory. As the pointers are then under the direct control of the programmer, we don't have to worry about a new version of LV stealthily moving things around as part of some new optimization or compression or whatever algorithm. First, to create a buffer:
create buffer snippet.png
create buffer snippet.png (18.4 KiB) Viewed 288 times

This uses the built-in LV routine DSNewPtr() to allocate a block of memory and return a pointer to it. These pointers can then be passed to the PS DLLs:
setup stream snippet.png

(there's an intermediate routine which creates several buffers at once; that's just to cut down on wiring clutter). For simplicity, this just implements streaming on channel A and nothing else.

Once the stream has started and data is coming in, the LV routine MoveBlock(), which is essentially equivalent to a C memcpy(), can pull out the latest chunk of streamed data:
read memory block snippet.png
read memory block snippet.png (22.3 KiB) Viewed 288 times

And, since we're doing manual memory management, we have to explicitly release the memory at the end using DSClrPtr():
release buffer snippet.png
release buffer snippet.png (13.53 KiB) Viewed 288 times


Putting it all together, the example code starts to look like this:
streaming loop snippet.png

We create the buffers as part of Set Up Stream (the feedback node is so that the setup routine knows whether or not the buffers already exist if it's called in subsequent loop iterations), start the stream, and then use MoveBlock essentially as a drop-in replacement for the Array Subset. At the end, free the buffer memory at the same time that we tell the DLLs to release the instrument handle. (Ignore the stuff in the lower half of the inner loop; that's me fiddling with various approaches for doing real-time processing of the stream without interrupting said stream)

There are a couple of ancillary advantages to this approach. By passing the pointers rather than individual wires with each array, we can cut down a lot on clutter by bundling the pointers either into an array (as I've done here) or a cluster; for multi-channel sampling, an array of clusters would work well, as you could then easily pass a single wire and then iterate over all active channels in a loop rather than have to handle each wire individually.
dmsilev
Newbie
 
Posts: 0
Joined: Fri May 12, 2017 4:38 pm

Re: Streaming example code and LV memory management

Postby Hitesh » Mon May 22, 2017 4:23 pm

Hi dmsilev,

Thank you for this interesting post.

We use the wrapper dll in order to copy data from the driver buffer for a channel to an application buffer for the same channel in order to ensure that, subject PC performance and requests being made for availability of data, the data is not lost from the device.

If you are happy for us to test and review your code, please submit a pull request on our GitHub repository.

Regards,
Hitesh

Technical Support Engineer
Hitesh
Site Admin
Site Admin
 
Posts: 2386
Joined: Tue May 31, 2011 3:43 pm
Location: St. Neots, Cambridgeshire

Re: Streaming example code and LV memory management

Postby dmsilev » Mon May 22, 2017 5:07 pm

Hi Hitesh,

I'd be happy to share my code. I confess I'm not too experienced with GitHub; the procedure seems to be for me to create a new branch, upload my files into that branch, and then generate a pull request. Is that correct? Alternatively, I can go low-tech and either attach a zip file here or email it to someone.

Best,
Daniel
dmsilev
Newbie
 
Posts: 0
Joined: Fri May 12, 2017 4:38 pm

Re: Streaming example code and LV memory management

Postby Hitesh » Tue May 23, 2017 8:13 am

Hi Daniel,

I would suggest the following:

1. Create a Fork of the project
2. Create a new branch if possible (call it something like streaming-update)
3. Submit a pull request

In your code, add a label in the vi files to indicate what changes you have made, along with your name.

Please make sure that your files are saved for LabVIEW 8.5 and in the appropriate driver/example folder e.g. ps2000a/32-bit-examples

Regards,
Hitesh

Technical Support Engineer
Hitesh
Site Admin
Site Admin
 
Posts: 2386
Joined: Tue May 31, 2011 3:43 pm
Location: St. Neots, Cambridgeshire

Re: Streaming example code and LV memory management

Postby dmsilev » Tue May 23, 2017 6:27 pm

OK, I think I managed to set up the pull request properly (if not, please let me know). The uploads are all in PS4000/64-bit examples.
dmsilev
Newbie
 
Posts: 0
Joined: Fri May 12, 2017 4:38 pm

Re: Streaming example code and LV memory management

Postby Hitesh » Wed May 24, 2017 10:40 am

Thanks!

A pull request has been received.

We will review it and provide an update.

Regards,
Hitesh

Technical Support Engineer
Hitesh
Site Admin
Site Admin
 
Posts: 2386
Joined: Tue May 31, 2011 3:43 pm
Location: St. Neots, Cambridgeshire


Return to LabVIEW

Who is online

Users browsing this forum: No registered users and 0 guests