LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Call Library node and multiple array copies

Hey everyone,
 
I am trying to do the following using a hybrid of C and Labview:
 
1.) Create an array in Labview
2.) Pass the array into 2 seperate DLLs at the same time
3a.) One DLL modifies the data and then updates a flag.  For example, the array created in 1 in 100,000 units long, this DLL modifies 999 units in one pass and updates the 1000th unit to say that the 999 units have been succesfully written.  It would do this 100 times in this example.
3b.) The 2nd DLL checks the flag unit set in 3a, and if the flag is a certain value, the 2nd DLL reads the 999 units modified in 3a and performs operations on them.
Note:  There is no read/write conflict here, since the only way 3b operates on the memory is if 3a has completed its operations and updated the flag.
 
The problem:
Labview creates 3 copies of the same array in memory.  Once in step 1, and 1 for each DLL.  This is problematic since the 2 DLLs can't communicate with each other anymore in the way that is described above, since the method above requires that the DLLs in 3a and 3b operate on the same memory locations.
 
The question:
How can I prevent Labview from creating multiple copies at the Call Library node so that my DLLs can operate on the same chuck of memory that is created in step 1.
 
Thanks,
Austin McElroy
0 Kudos
Message 1 of 11
(3,934 Views)

Hi Austin McElroy,

So, you may want to avoid calling the array in memory. It might make more sense to input the array into your first DLL and then pass the output array into the second DLL. That way you're not worrying about the array's location in memory. If you want to check the value of an item in the array before passing the array into the second DLL, use an Index Array VI.

Regards,

Hillary E
National Instruments
0 Kudos
Message 2 of 11
(3,913 Views)
Hey Hillary, thanks for the response.  I am trying to move my code from a serial approach to a parallel approach.  My example might have been a better one, so let me say that one of the DLLs is an acquisition DLL and the other a processing DLL.  By doing the flag method posted above, I can simultaneously acquire and process when a buffer is full and a flag bit is flipped.  This way, I can designate one thread to one DLL, and give the other DLL the rest of the threads.  However, this relys on having the DLLs communicate in parallel which can easily be done they can write/read from the same memory space.  Is there no way to prevent Labview from copying the initial array and only passing the pointer to the first location of the initial array?

0 Kudos
Message 3 of 11
(3,907 Views)
What you planning isn't workable. Sharing memory even with a proper locking mechanism is difficult to do right. And what you have suggested isn't guaranteed to work correctly due to instruction reordering which can and likely will be done by the compiler and the cpu (even if your lucky and it does work, a change in compiler settings or a new compiler can break it), also if the size of a element in your array can't be written atomically then you could end up working on garbage elements. In short shared memory parallel programming is very hard, and without proper locks it becomes extremely hard (see http://en.wikipedia.org/wiki/Memory_barrier for a key piece if your curious).

Also your proposed design isn't even parallel since only one dll can accessing the memory at a time (due to the flags which as I've said aren't guaranteed to work). Unless 3a can write while 3b works on it but that's going to break if 3a overtakes 3b. So you've basically created a giant headache for no gain. I'm sorry if I sound harsh, I'm trying to make it clear that this is a very bad way to go about it.

I would suggest using a producer and consumer design using LabVIEW queues. Acquiring and processing can really work in parallel and you can even use C DLLs to do the work if needed (just be sure to set the thread to any thread instead of the UI thread in Call Function Library node, and that the two functions don't share anything in memory that can be written to). Although pure LabVIEW would be easier to debug (and you may even get to take advantage of some implicit parallelism in the algorithms).

Matt W

PS. If you really want to learn the hard way (I suggest against it since even if it does "work" it'll probably have subtle bug in it), you can allocate the array in a C DLL method and pass it around in LabVIEW as a pointer sized integer.You can use another C Method to copy the data into an array from LabVIEW if you need LabVIEW to do something with it.
0 Kudos
Message 4 of 11
(3,900 Views)
I can only acknowledge everything Matt has said. What you try to do will not really give you an advantage but will cause you lots and lots of headaches because it will sometimes simply not work right. Your proposed setup is something every programming class will strongly discourage because it is almost not managable, and even if you do get it right likely to break in subtle ways on multi CPU, multi core or even hyper threading architectures. Leave it at that and try to do some other more productive things.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 5 of 11
(3,882 Views)
Austin- I agree that the "shared memory" scheme which you proposed opens up a can of worms for the reasons outlined by Matt. However, your question about why LabView is duplicating an array when it calls a single DLL is valid and highly relevant to many applications.

If the Call Library Node is the only downstream function which uses that array, I don't see why the LabView compiler would make a duplication. I was always under the impression that when a subVI (or DLL call) was made, that a memory copy did not occur unless, of course, that memory is needed by LabView elsewhere by wiring it off to another block in parallel. According to NI white papers I've read on memory management in LabView, arrays are not supposed to be copied multiple times if they are not needed in their original form downstream.

I hope someone can please clarify this subtlety in the LabView complier/memory management.
Thanks, NK
0 Kudos
Message 6 of 11
(3,881 Views)
Ok, so as nk said, even if the idea is terrible why is Labview making extra copies?  If I have 2 DLLs in serial to avoid the flag idea, and I am working with  datarates of 100MB/s coming off of my acq. card, that is  100MB allocated for the initial array, 100MB allocated for the first DLL and 100MB allocated for the 2nd DLL, per second.  Perhaps even more allocations and copying from C back into Labview (I am unsure of this, I will test it tomorrow).  This is alot of memory being allocated and copied extraneously.  Is there a way to prevent Labview from doing this?
0 Kudos
Message 7 of 11
(3,853 Views)


@AustinMcElroy wrote:
Ok, so as nk said, even if the idea is terrible why is Labview making extra copies?  If I have 2 DLLs in serial to avoid the flag idea, and I am working with  datarates of 100MB/s coming off of my acq. card, that is  100MB allocated for the initial array, 100MB allocated for the first DLL and 100MB allocated for the 2nd DLL, per second.  Perhaps even more allocations and copying from C back into Labview (I am unsure of this, I will test it tomorrow).  This is alot of memory being allocated and copied extraneously.  Is there a way to prevent Labview from doing this?


And LabVIEW doesn't make copies if it doesn't need too. For this to work however you need to pass the array through the CLN (input it on the left side and output it at the right side of the CLN and from there wire it to the next function), not branch it. That should even work if you configure the array parameter to be a C array data pointer (since LabVIEW will pass the pointer to the actual data to the DLL), but it definitly works without copies for LabVIEW array handles.
Then LabVIEW won't make a copy (except maybe in some older versions). If  you branch the wire however, LabVIEW has no choice but to create at least one copy to satisfy data flow contraints.
This doesn't mean that the first DLL function could store the array pointer and operate on it after it has returned since a C function once returning control to the caller has absolutely no control over a pointer it got passed anymore. At the time your DLL might decide to access that pointer LabVIEW quite likely might have left the diagram already and consequently deallocated or reused the handle for something else, causing your DLL to corrupt memory. Even if you decide to use events to signal the second function to not return before the data has been modified by the first, you create a monster of complexity that will sooner or later blow in your face. Either the user might decide to abort the programm mid term and your second function never receives the signal so never returning, making your application simply hang in there with no other option than to kill it through the task manager, or someone will go modify your little program not knowing the (unlogical) dependency of those two calls and creating something that simply works very wrong or if you are very lucky will crash with an access violation exception early on.

Rolf Kalbermatter


Message Edited by rolfk on 03-24-2008 01:39 PM
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 8 of 11
(3,835 Views)

Hey Rolf,

Thanks for the indepth response.  I tried a very simple example which duplicates what you said to do:

1.) Allocates memory in Labview

2.) Passes this data into a single C DLL

Here is a picture of the block diagram with the memory allocation  tool activated (variables obfuscated for your protection).  In addition, when the program is run, 2x the memory that I allocated actually gets allocated, which basically confirms what the Labview allocation tool is showing.  The data is passed using the Array pointer option in the C node.  Even if I wire up the right side of the C node, there are still 2 buffers being allocated.

Thanks,

Austin McElroy

 

0 Kudos
Message 9 of 11
(3,820 Views)


@AustinMcElroy wrote:

Hey Rolf,

Thanks for the indepth response.  I tried a very simple example which duplicates what you said to do:

1.) Allocates memory in Labview

2.) Passes this data into a single C DLL

Here is a picture of the block diagram with the memory allocation  tool activated (variables obfuscated for your protection).  In addition, when the program is run, 2x the memory that I allocated actually gets allocated, which basically confirms what the Labview allocation tool is showing.  The data is passed using the Array pointer option in the C node.  Even if I wire up the right side of the C node, there are still 2 buffers being allocated.

Thanks,

Austin McElroy


You haven't proven anything yet. The integer array you pass to the DLL happens to be a constant array and due to constant folding this array is allocated at load time in read only memory and not on the heap. Accordingly LabVIEW has to reallocate a new array to pass to the DLL, since it has to assume that the DLL might be modyfying the memory. Without reallocating a handle the memory pointer would be read only and any attempt by the DLL to modify that memory in any way will cause a general protection error.

Try to replace the 1 constant for the array data type with a control on the front panel and then see if the buffer allocation is still done. I doubt it very highly.

In fact you can see that I'm right when you look at the second floating point array. No memory allocation dot is done there.

Rolf Kalbermatter


Message Edited by rolfk on 03-24-2008 07:31 PM
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 10 of 11
(3,809 Views)