LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

What is the most efficient way to pass LV data to a dll?

For efficiency, this question primarily becomes important when passing large arrays, structures containing large arrays, or generally, any large block of data to a dll.

The way the dll setup appears and the .c file it create for the dll call, it appears that labVIEW directly passes data in whatever native passing format LV requires without copying the actual data if you select the "Adapt to Type" as the "Type" option. If I pass an array, for example, the .c file contains the type definition of a labVIEW array, i.e., (size,data), and depending whether I select handle or handle pointer, the data passed is either a handle or handle pointer to the array. Likewise, if I pass a LV structure, the .c file will con
tain the typedef to the structure and the data passed is either a pointer, or pointer to a pointer. These are, I believe, labVIEW native types and do not require copying.

On the other hand if an array is passed as an array type, then it is converted to a C array that requires LV to copy the array on both sides of the call.

I further assume all structures can be passed to the memory manager to be manipulated, although I'm actually not sure that you could resize an array pointer in the dll. That seems a bit dubious, but then I guess upon return LV could query the memory manager to determine the array pointer size.

That�s how I would think things work. If not, could someone please correct me?

Kind regards,
Eric
0 Kudos
Message 1 of 16
(4,049 Views)
....
> I further assume all structures can be passed to the memory manager to
> be manipulated, although I'm actually not sure that you could resize
> an array pointer in the dll. That seems a bit dubious, but then I
> guess upon return LV could query the memory manager to determine the
> array pointer size.

For details on data shapes and functions for dealing with them, refer to
the External Code or CIN manual. I haven't looked at it in a few
releases, so I don't know the current name, but it will give the
details. It seems like you are also using the Create .c file menu item,
which helps to get the correct structs for using on LV types.


In general, the LV types are always going to be efficient. The calls
using all other types do not always c
opy the data, it depends on if we
could find a clever way to avoid it.

Let me go over the memory management issue above real quick since this
is the stickiest issue for most people. If you are dealing with the LV
types, then you can resize anything in the DLL that you can resize on
the diagram -- you just have to do it correctly. Don't ever call
realloc or swap out a ptr LV gives you with one you malloc, alloc, or
new, and never free or delete one of the pointers passed to you. If you
have a LV handle, then you can directly call the LV functions for
resizing handles, but you have to know what you are doing to compute the
size, call the correct function, and you also need to update the
elements-size field yourself. That is why there are the functions to
set Arrays and strings specifically. Using those, many of the details
will be handled for you.

If you have more specific questions, fire away.

Greg McKaskle
Message 2 of 16
(4,048 Views)
Greg,

There are two relevant documents which are distributed with labVIEW, in labVIEW 6i, (hey, I'll get around to upgrading), the first is titled, "Using External Code in LabVIEW", the second is application note 154, "LabVIEW Data Formats".

Actually, a statement Wiebe@air made on my previous question regarding dll calls, "Do dll calls monopolize the calling thead?� provoked this line of questions. Based on other things he has said, I gather he is also using dlls. So as long as we're here let me ask the next question...

If labVIEW must make a copy of the passed data, does it show up as additional memory blocks in the vi profiler? In other words, can you use the profiler to infer what labVIEW is doing, or as you put it, infer whether there is a clever passing method available?

As a personal note Greg:

First, as a one time engineering student and teaching assistant, I don�t recall hearing or using the terms �magical�, or �clever�. Nor I might add, do I find them in print elsewhere in technical journals. While I don�t mind NI marketing in their marketing documents, used here in this mostly educational forum, they strike me as arrogant, and/or pompous.

I like NI�s products because they work and are reliable. I doubt it has anything to do with magic, has somewhat more to do with being clever, but is mostly due to the dogmatic persistence of your engineers. I rather doubt any of them adjoin the term �magical� or even �clever� to their solutions. I believe the term �best� is generally accepted with the qualifier �I�ve or we�ve found�. At least, that has been my engineering experience.

Second, many of my questions I can sort out on my own, but I figure as long as your willing to answer the questions, then your answers are generally available to others. The problem is that one question seems to lead to another and specific information gets buried in a rather lengthy discourse. When I come here with a specific question, it would be nice to find it asked and answered specifically rather than buried in the obscurity of some other question. As such, at some point in these discussions it might be appropriate to reframe a question and put at the top. In my opinion, that decision is primarily yours as you have a better feel for the redundancy of questions asked and/or your answers.

Anyway, the next question I'm posting at the top is, "Do the handles passed to a dll have to be locked down to insure other threads don't move the data?"

Thanks,
Kind Regards,
Eric
0 Kudos
Message 3 of 16
(4,048 Views)
> ... In other words, can you
> use the profiler to infer what labVIEW is doing, or as you put it,
> infer whether there is a clever passing method available?

I can't be certain without testing it using a diagram, but they should,
and I'm pretty sure that they do.

>
> As a personal note Greg:
>
> First, as a one time engineering student and teaching assistant, I
> don?t recall hearing or using the terms ?magical?, or ?clever?. Nor I
> might add, do I find them in print elsewhere in technical journals.
> While I don?t mind NI marketing in their marketing documents, used
> here in this mostly educational forum, they strike me as arrogant,
> and/or pompous.

As long as we are getting personal, let me pull back the e-curtain and
explain who I am. I am a C/C++ programmer on the LV development team.
I've been on the team over 12 years now. I read the comp.lang.labview
list from home and try to answer what I can.

I certainly don't mean to use the word clever to sound pompous, I just
use the terms that we use in the development group. If I wrote the code
that is being discussed, I wouldn't use the term, but someone else wrote
it, and it is clever. As for the magic reference, I had a class in
college called The History of Technology. One of the lectures was about
how technologies we don't understand are essentially magic.
Incandescent lighting is perfectly understandable, to most engineers,
but to people who don't know how it works, there is this toggle stick on
the wall that makes a little piece of the sun appear on the ceiling.
Similarly, lots of computer algorithms like the ones for image pattern
matching, seem to almost be alive the way the "see" and percieve what is
in front of them. In a sense, that is the goal, to make magic via
technology, so that it isn't complicated, it easily does what you want.
If course magic also implies that we won't tell you how it is done.
But that is what this forum is for. Ask away.

> ... The problem is that one question seems
> to lead to another and specific information gets buried in a rather
> lengthy discourse. When I come here with a specific question, it
> would be nice to find it asked and answered specifically rather than
> buried in the obscurity of some other question.

I agree that you aren't getting the best answers to your questions. I
hope that you are making progress, and I'd encourage you to make them as
specific and targeted as possible.

Greg McKaskle
0 Kudos
Message 4 of 16
(4,048 Views)
Eric,

Let me tell you something about me too...

I've been working with LabVIEW for (just) 4 years. That is, 40 hours a week
professionally, 10 hours a week privatelly. I've started with LV4, and went
through all versions and revisions until 6.0.2 (6.1 will come soon, but
first I have to finish some major projects.

During this time I've been working on lots of interfaces with the windows
OS. Some 'dll' things I've worked on: OpenGL interface, MSXML driver,
keyboard hooks, mouse hooks, GDI interfacing, calling LV dll's from
assembler, calling assembler dll's from LV, creating threads, using serial
interrupts, etc. I'm now (also) working on a way to automatically generate
documentation (much more then the 'export VI stings') from a VI. This
requires 'under the hood' knowledge about how VI's work.

When I had to make a fast routine for a project one time, I choose
assembler, because I had this knowledge. Also, I wanted to use pure SIMD
opperations. The operation had to modify an array of DBL's. The SIMD uses
the same format (IEEE 754, I think), so it was easy. But when it came to
testing, it appeard that the routine only paid off if the routine was 'long'
enough. The routine was n*O^2, where n was a parameter. When the array was
large, and n small, the overhead of copiing the array to modifiable memory
was relativelly large, and the LV routine was faster.

When I get a pointer to a LV array, I can use this pointer to modify the
data in the array. This can (I think) only be done if LV copied this data,
just like LV is doing when a wire is split to be modified.

It might be that this copiing can be prevented, e.g. by using other data
types, or fiddling with threads and reentrance... If you want to optimally
benefit from dll's I'd look for a way to keep the data in the dll space, or
pass it once at initialisation. You could use CreateHeap, HeapAlloc,
AllocGlobal, and other functions. You can use these functions in LV, or in
the dll. Once you have a pointer to the (one and only) data space, you can
use this to pass to the dll functions.

I think LV does not show the memory in question in the profiler, but I'm not
sure.

Using the "Adapt to type" option might just result in a internal convertion
during 'compile' time, and might be exactly the same as doing it yourself.

Perhaps you can share a bit about the application you are making, or at
least why you need the speed you are seeking?

Regards,

Wiebe.


"Eric6756" wrote in message
news:50650000000500000025C60000-1042324653000@exchange.ni.com...
Greg,

There are two relevant documents which are distributed with labVIEW,
in labVIEW 6i, (hey, I'll get around to upgrading), the first is
titled, "Using External Code in LabVIEW", the second is application
note 154, "LabVIEW Data Formats".

Actually, a statement Wiebe@air made on my previous question regarding
dll calls, "Do dll calls monopolize the calling thead?" provoked this
line of questions. Based on other things he has said, I gather he is
also using dlls. So as long as we're here let me ask the next
question...

If labVIEW must make a copy of the passed data, does it show up as
additional memory blocks in the vi profiler? In other words, can you
use the profiler to infer what labVIEW is doing, or as you put it,
infer whether there is a clever passing method available?

As a personal note Greg:

First, as a one time engineering student and teaching assistant, I
don't recall hearing or using the terms "magical", or "clever". Nor I
might add, do I find them in print elsewhere in technical journals.
While I don't mind NI marketing in their marketing documents, used
here in this mostly educational forum, they strike me as arrogant,
and/or pompous.

I like NI's products because they work and are reliable. I doubt it
has anything to do with magic, has somewhat more to do with being
clever, but is mostly due to the dogmatic persistence of your
engineers. I rather doubt any of them adjoin the term "magical" or
even "clever" to their solutions. I believe the term "best" is
generally accepted with the qualifier "I've or we've found". At
least, that has been my engineering experience.

Second, many of my questions I can sort out on my own, but I figure as
long as your willing to answer the questions, then your answers are
generally available to others. The problem is that one question seems
to lead to another and specific information gets buried in a rather
lengthy discourse. When I come here with a specific question, it
would be nice to find it asked and answered specifically rather than
buried in the obscurity of some other question. As such, at some
point in these discussions it might be appropriate to reframe a
question and put at the top. In my opinion, that decision is
primarily yours as you have a better feel for the redundancy of
questions asked and/or your answers.

Anyway, the next question I'm posting at the top is, "Do the handles
passed to a dll have to be locked down to insure other threads don't
move the data?"

Thanks,
Kind Regards,
Eric
0 Kudos
Message 5 of 16
(4,048 Views)
> When I get a pointer to a LV array, I can use this pointer to modify the
> data in the array. This can (I think) only be done if LV copied this data,
> just like LV is doing when a wire is split to be modified.
>
> It might be that this copiing can be prevented, e.g. by using other data
> types, or fiddling with threads and reentrance... If you want to optimally
> benefit from dll's I'd look for a way to keep the data in the dll space, or
> pass it once at initialisation. You could use CreateHeap, HeapAlloc,
> AllocGlobal, and other functions. You can use these functions in LV, or in
> the dll. Once you have a pointer to the (one and only) data space, you can
> use this to pass to the dll functions.

Any data copies needed for DLLs
is determined by the inplace algorithm
much like for other nodes. Since the LV compiler doesn't know whether
or not the DLL will modify the input parameters, LV has to protect
itself and assume that all data passed by pointer may be written to. If
the parameter is needed for another node, then that will require a copy,
but if LV can arrange it, the allocation will belong to the DLL and
allow to be written on and passed back out with no copies. There isn't
any need to mess with reentrancy or threads.

Greg McKaskle
0 Kudos
Message 6 of 16
(4,048 Views)
Greg,

Your use of magic is very light hearted. There is a darker side to magic though. Spend some time in the third world and you will find that magic takes on rather more significant role in people�s lives. It embodies power, the manipulation of the ignorant, and the perpetuation there of. The term magic is a human invention to explain the unexplainable, and is associated with a very sorted history.

As engineers I don't think it's wise to advance the notion that what we build or create is like magic; neither do I believe it's wise for medical doctors to advance the notion what they do is like magic. Imagine a pharmacist advancing the notion that drugs are like magic. Sorry Greg� I appreciate your enthusiasm, motivation and in
tent, but mixing science with the supernatural just doesn't work for me.

Now that's an unexpected tangent...

�back to the original question. I don�t know if you noticed, but your statement and Weibe�s testimonial below don�t jive. So� as apparently I�ve insulted you both, I think I�ll take this discussion back to him.

Oh, by the way, I think you probably had a few phone conversations with my brother back when we were in the LV 3.x beta program. So yes, I knew your credentials; you have laid them out for me here before as well. I didn�t intend this to be a credential swapping discussion despite my introductory comment and my backhanded compliment.

Kind regards,
Eric
0 Kudos
Message 7 of 16
(4,048 Views)
Wiebe,

I see that Greg has already replied to you.

Sorry, I didn't really mean to have everyone pulling out their licenses here.

At the moment though it is late so I'll get back to you tomorrow. In the mean time I'm uploading a vi library. It contains, I think, 5 vis and is compiled under LV6.0.2 so you should be able to load it. When you open the library, select "Boolean Test.vi". It is not well documented but basically it compares LV operations versus dll operations for boolean bitwise arrays and LV bytewise arrays. One routine "LV Bytes to Bits.vi" is duplicated in the dll.

Anyway, I'm going to hit the sack...

Thanks,

Kind Regards,
Eric
0 Kudos
Message 8 of 16
(4,048 Views)
Wiebe,

You said: "When I had to make a fast routine for a project one time, I choose assembler, because I had this knowledge. Also, I wanted to use pure SIMD opperations. The operation had to modify an array of DBL's. The SIMD uses the same format (IEEE 754, I think), so it was easy. But when it came to testing, it appeard that the routine only paid off if the routine was 'long'enough. The routine was n*O^2, where n was a parameter. When the array was large, and n small, the overhead of copiing the array to modifiable memory was relativelly large, and the LV routine was faster."

Actually, I found in the uploaded file, the case was just reversed. But I'm not comparing apples to apples except in one routine.

The point of these routines is to look at the relative merits of using byte wise versus bit wise Boolean values. This is a subset of a library of routines to deal with bit wise Boolean values.

If you downloaded the above file you will find a top-level routine named "Boolean Test.vi". The top-level routine just creates a random LV Boolean array. You can adjust the array size and Boolean distribution in the array.

The array is compressed into a bit wise Boolean array both in the dll and in LV. The results of those operations are compared to insure my dll is functioning properly. (My C is pretty rusty so I've to write everything in LV first and compare the results.)

The bit wise array is then passed to another dll call that counts the number to true values in the array. The original byte wise array is passed to two LV routines that also count the number of true values in the array. All values are compared to insure everyone has the same answer.

All subvis' are subroutine subvis so they must run sequentially, and all run as fast a LV can execute them.

When you profile these vi's you will find the memory use for all the subvi's is about the same except "LV Count True Bytes 1". The diagrams explain why. You will note that both the labVIEW vi "LV Boolean Bytes to Bits.vi" and the equivalent dll wrapper vi "Boolean Bytes to Bits.vi" create new arrays which do not show up in the memory profile. As the dll is using the LV memory manager, I can understand why the profiler may not know about the memory assignment. I do not understand why the memory assignment does not show up in the equivalent LV function. It seems somehow it gets attached to the caller rather than the subvi.

In this test, as you reduce the size of the Boolean array, you will find the relative advantage of the dll calls is reduced, presumably due to the call overhead. This seems to verify what Greg has said.

I'm not sure I understand exactly what you are doing in assembly, or what the equivalent LV diagram might look like. If you are replacing a series of LV vector operations, I think you would be hard pressed to optimize them in C or assembly. If you talk to people who write C/C++ code for a living, they'll tell you that trying to advise today�s compiler how to optimize its registry use is a waste of time. I've been told that, like computer chess programs, today�s compilers will frequently beat your own optimization schemes.

That is not to say that program operation sequencing, the elimination of redundant operations, and the use of as few variables as possible can't make a big difference though. Compilers aren't that smart.

In sum Wiebe, I don't know. We seem to have contradictory results or at least conclusions. If you see something I'm missing in my testing, please advise me. I'm interested in what you looking at, so if you can, upload it.

Thanks,
Kind Regards,
Eric"
0 Kudos
Message 9 of 16
(3,747 Views)
> Sorry Greg? I appreciate your enthusiasm, motivation and intent, but
> mixing science with the supernatural just doesn't work for me.


> well. I didn?t intend this to be a credential swapping discussion
> despite my introductory comment and my backhanded compliment.
>

Hmm. I got the impression that you were unhappy with my choice of terms
and felt that a developer or engineer would never use them. I just
wanted to make sure you were aware that I have been and been around LV
developers for awhile now. Language is a cool thing, and we don't use
just the stuffy part of it.

As for the discussion, at some point you will need to just jump in and
write it. Be sure to look at the results of the Bit Twiddling
challen
ge, as lookup tables and Boolean integer arithmetic will make
most packed Boolean handling a piece of cake and execute quickly too.

Yeah, I know, but it could be even faster if... But that is always
true. There are several approaches to developing SW, with the two ends
of the spectrum being waterfall and iterative. Waterfall does tons of
planning and puts off the implementation till the very end, with the
idea of writing it once and writing it correctly. Iterative approach
trades some of this planning in for doing a first prototype, taking some
measurements, and then reimplementing some portions based upon what you
learn.

I'm not meaning to take us off on another tangent, but these questions
have been going on for quite some time now.

Greg McKaskle
0 Kudos
Message 10 of 16
(4,048 Views)