LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

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

Eric,

Sorry, attachments (and the message that the attachments are in) don't show
up in Outlook express. I haven't seen any of them.

When I tried my little experiment, I was using LV4, so perhaps this is all
changed know. Stupid of me to forget that this might be important...

>"Eric6756" wrote in message
news:5065000000050000001BC70000-1042324653000@exchange.ni.com...
>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.

The routine was replacing a large array, with a smaller array. Each element
of the smaller array had to be the average of the corresponding elements in
the larger array. But there were some twisted things in the routine. E.g.
each part of the large array that was averaged, had to be the same size. The
remainder of the large array had to be copied.

The assembler code was 600% faster then the fastest LV code that I could
come up with.

My motivations for using assembler are:

+ it's free,
+ it's small,
+ it's fun,
+ I understand it,
+ I'm used to it.

Not at all very good arguments, but for me it's enough. I'm trying to shift
to VC++, but it takes time, because I don't really use it (, but use LV and
ASM instead).

>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.

First, the difference might be explained by the newer version of LV.
Second, your results are more satisfying, so I'm willing to exept them...
Third, a little experiment might be conclusive:

Make a dll, with an array as input.
Pass the pointer to the dll as the return value.
Put the dll several times behind each other.
All return pointers should be the same???

It this was done on an LV4 machine, everything should become clear, I think?

Regards,

Wiebe.

>Thanks,
>Kind Regards,
>Eric"
0 Kudos
Message 11 of 16
(999 Views)
Wiebe,

You said:�Sorry, attachments (and the message that the attachments are in) don't show up in Outlook express. I haven't seen any of them.�

If you use your web browser to come here, http://exchange.ni.com/servlet/Redirect?id=8829120, the downloads are available from links located beneath the associated text. In this case the link is title �dll testing stuff�.

You said:" The routine was replacing a large array, with a smaller array. Each element of the smaller array had to be the average of the corresponding elements in the larger array. But there were some twisted things in the routine. E.g. each part of the large array that was averaged, had to be the same size. The remainder of the large array
had to be copied. The assembler code was 600% faster then the fastest LV code that I could come up with."

Based on your description, 6x faster in assembly is a very believable figure.

You said: "First, the difference might be explained by the newer version of LV. Second, your results are more satisfying, so I'm willing to exept them... Third, a little experiment might be conclusive:

Make a dll, with an array as input.
Pass the pointer to the dll as the return value.
Put the dll several times behind each other.
All return pointers should be the same???

It this was done on an LV4 machine, everything should become clear, I think?"

Hey, now there's an idea. It gets right to the point (�so to speak�sorry that wasn't intentional). Sometimes things aren�t obvious until they�re obvious, but anybody reading this ought to be amused.

Thanks Wiebe,
Kind regards,
Eric
0 Kudos
Message 12 of 16
(999 Views)
Greg,

Yes... but... but... but... ...OK, I'll go play.

Thanks,
Kind Regards,
Eric
0 Kudos
Message 13 of 16
(1,300 Views)
Wiebe,

I ran a test both in labVIEW 4.1 and LabVIEW 6.0.2 and came up with the same results. My pointer didn't change across the dll calls. I tried 2,3,and 4 consecutive calls. The pointer remained the same. I also put in random array initialization, size and values, to bounce the data around. The pointer changes, but not across the dll calls. I also split the data path and looked at the pointers of each path; they were different but again across consecutive dll calls I get no change.

The C code was just:

_declspec(dllexport) unsigned long pointtest(unsigned long TestParameter[]);

_declspec(dllexport) unsigned long pointtest(unsigned long TestParameter[])
{

return((unsigned long) TestParame
ter);

}

Any other ideas?

Kind Regards,
Eric
0 Kudos
Message 14 of 16
(999 Views)
Wiebe,

OK, I finished this study. After putting some timers around the dll calls I found there is no relationship between the call time to a dll and the array size either in LV 4.1 or LV 6.0.2.

I did find one interesting point though in LV4.1:

1) when passing arrays through sequencing nodes, While loops, and For loops, they are copied at the boundaries. I might have know that at some time but had forgotten it. You can avoid this by passing the arrays through loops with shift registers, but I don't think you can avoid it in a seqencing node.

Actually I was kinda surprised because there is no obvious reason for the data to be copied. I don't know if LV 6.0.2 does the same but when I have som
e more time to play, I'll look at it as well as some of the other nodes.

When you compare the performance of LV 4.1 with LV 6.0.2 you'll find that the dll call is slower in 6.0.2 by about 30%, I suspect due to multithreading. But, you'll also find the variance in the call times are somewhat less in 6.0.2. And of course, 30% of virtually nothing is only significant if your doing virtually nothing in the dll.

I'm uploading the file. Simple as it is, it is useful when trying to isolate where labVIEW is copying data. There are both LV 4.1 and 6.0.2 llb files. The top VI is "Test dll data pass.vi". The dll contains two functions as follows:

_declspec(dllexport) unsigned long GetPointer(unsigned long AnyPtr32)
{
return(AnyPtr32);
}


_declspec(dllexport) unsigned long HandletoPointer(unsigned long *AnyHdl32)
{
if(AnyHdl32!=NULL)return(*AnyHdl32);
return(0xFFFFFFFF);
}

Again, thanks for suggesting it Wiebe.

Kind Regards,
Eric
0 Kudos
Message 15 of 16
(999 Views)
Eric,

Maybee someone can test it on LV4? This would explain my results... Perhaps
I was yous mistaken...

Anyway, it's good to know that it is like it is. It could save tremendous
amounts of processor time.

Regards,

Wiebe.

BTW: this is the asm code:

pointtest proc
pop DUMMY ; store return address
pop eax ; first parameter
push DUMMY ; restore return address
ret
pointtest endp


"Eric6756" wrote in message
news:5065000000050000002DC80000-1042324653000@exchange.ni.com...
> Wiebe,
>
> I ran a test both in labVIEW 4.1 and LabVIEW 6.0.2 and came up with
> the same results. My pointer didn't change across the dll calls. I
> tried 2
,3,and 4 consecutive calls. The pointer remained the same. I
> also put in random array initialization, size and values, to bounce
> the data around. The pointer changes, but not across the dll calls.
> I also split the data path and looked at the pointers of each path;
> they were different but again across consecutive dll calls I get no
> change.
>
> The C code was just:
>
> _declspec(dllexport) unsigned long pointtest(unsigned long
> TestParameter[]);
>
> _declspec(dllexport) unsigned long pointtest(unsigned long
> TestParameter[])
> {
>
> return((unsigned long) TestParameter);
>
> }
>
> Any other ideas?
>
> Kind Regards,
> Eric
0 Kudos
Message 16 of 16
(999 Views)