LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

SetThreadAffinityMask Equivalent in LabVIEW?

Is there any equivalent to the Windows API function SetThreadAffinityMask()  in LabVIEW?
My requirement: I have two threads (While loops) running in LabVIEW, in a dual-core computer (Windows XP). I want to run one thread (while loop) in one core (CPU) and the other thread in the other core. Is there any way to do it in LabVIEW 8.2.1?
I have done it in C++ using SetThreadAffinityMask() Windows API function.
If I can get a HANDLE to the thread (while loop), probably I can pass this HANDLE to a CIN (Code Interface Node) and lock it to a CPU using SetThreadAffinityMask(). But, how can I get a handle to a while loop?
I tried to put the two while loops in two different VIs and tried to get handles to the VIs. The idea was to lock the two VIs to two different cores. I could get a RefNum to the VI using the VI Server; but is this the HANDLE expected by SetThreadAffinityMask()?. I passed the VI RefNum to the CIN, and used it as the thread handle while calling SetThreadAffinityMask() function. It did not work (I was watching the CPU usage in Task manager Performance panel).
Any solutions?
 
GKB
 
 
0 Kudos
Message 1 of 9
(5,329 Views)

OK. I did some more research. Now I can programmatically set the Process Affinity in LabView (found an articale in the knowledge base, thank you). I used the Call Library Function Node (with GetCurrentProcess()) to get the handle of the current LabVIEW process; passed this handle into a CIN and locked it to a CPU using SetProcessAffinityMask() API function. But this locks the whole LabVIEW process to that CPU. Still trying to find a way to lock a single thread (while loop) to one CPU. Tried to use Call Library Function (with GetCurrentThread()) , passed the handle to a CIN and tried to lock it to a CPU using SetThreadAffinityMask(). It did not work.

GKB

 

0 Kudos
Message 2 of 9
(5,294 Views)
Here's one idea I had which is a little weird, I must admit, but might work for you. (I don't know of any direct ways to accomplish this.)

If you have the LabVIEW Application Builder, you can build LabVIEW VIs into DLLs, where you set certain VIs to be exported functions in the DLL. The trick is that when another process calls a LabVIEW-built DLL, that exported function will start running in the same thread that called it.

You could use this by doing two things:
1. Wrap each loop in your LabVIEW VI into its own VI. Create a DLL for your app where each separate loop VI is its own exported function.
2. Create a C++ wrapper that spawns two threads and sets their affinity to the two CPUs. Then have each thread call one of the two exported functions to start the two LabVIEW loops. Unless these VIs have a good reason to spawn new threads (such as jumping to the UI thread for property node calls), they'll stay in the threads that called them.
Jarrod S.
National Instruments
0 Kudos
Message 3 of 9
(5,287 Views)

Hi Gopal,

 

Do you still have the code that locks LabVIEW process to one CPU by calling GetCurrentProcess()) and SetProcessAffinityMask()? If yes, can you e-mail me the code? Thanks!

 

Sergey < sliberman@solidusintegration.com >

Message Edited by sliber on 06-07-2010 12:37 PM
0 Kudos
Message 4 of 9
(4,928 Views)

Gopal,

 

Never mind. I figured out how to do it.

 

Regards,

 

Sergey

0 Kudos
Message 5 of 9
(4,913 Views)

 


@sliber wrote:

Gopal,

 

Never mind. I figured out how to do it.

 

Regards,

 

Sergey


 

Sergey-

 

How about posting your solution with a brief discussion?  It might help several others in the future and really that kind of stuff is what the forums are about.  Smiley Wink


"Should be" isn't "Is" -Jay
0 Kudos
Message 6 of 9
(4,830 Views)

Jeff,

 

Sure thing. Attached is a snippet from my code (Affinity0.png). The rationale for this was that some old RS232 drivers are unstable on multicore/multiCPU computers; confining your program to run on one core only ensures their stability. A call to this function can be made in any place in your program.

 

A different solution to the same problem is to use a free program called runfirst.exe (you can find it here: http://www.activeplus.com/Products/RunFirst). Most likely it uses the same call to the Windows kernel. The difference is that you can use that call to start your program on a single core from the very beginning. A snippet for that call is also attached (RunFirst.png). You'll need to place runfirst.exe into the same folder as the VI that invokes it.

 

Regards,

 

Sergey

Download All
0 Kudos
Message 7 of 9
(4,802 Views)

It's possible to modify the snippet above using GetCurrentThread() and SetThreadAffinityMask() .

But there is one thing to keep in mind: According to MSDN GetCurrentThread() returns a pseudohandle that can't be used by other threads:

 

http://msdn.microsoft.com/en-us/library/ms683182%28VS.85%29.aspx

 

IMHO you can't just pass it to a CIN, perhaps it would work using DuplicateHandle() . But if you call GetCurrentThread() immediately followed by SetThreadAffinityMask() from within the same while loop it works.

0 Kudos
Message 8 of 9
(4,756 Views)

See Andrey's post (number 14 in this thread).

 

This is a preview of the FP of the code he posted.

 

008nc.png

 

 

Problem solved?

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 9 of 9
(4,747 Views)