I want to parallelize with threads (not with multi-process) a native c++ code which use a DLL (Compute.dll) which is not thread-safe.
Actually, I have a kind of loop that I can parallelize :
for(int i = 0; i < x; i++) {
ComputeDLL.DoWork(i); // DLL API Call not thread-safe
}
I identify a way to parallelize my native code : Clone and rename Compute.dll in Compute1.dll, Compute2.dll, ..., ComputeN.dll and use one dll by thread. So for the link, in the same way, i have to duplicate Compute.lib in Compute1.lib, Compute2.lib, ..., ComputeN.lib
With this solution, I have to duplicate code in my app to define multiple ComputeDLL class : ComputeDLL1, ComputeDLL2, ... ComputeDLLN with an explicit static link :
#pragma comment(lib,'Compute1.lib'); // for ComputeDLL1.h
#pragma comment(lib,'Compute2.lib'); // for ComputeDLL2.h
etc.
Can you tell me if this solution will work ?
In this solution :
Is there an another cleaner good way to solve my problem ? May I use LoadLibrary() ?
Thanks
Nb : I don't want to use muli-processing because in my real case, I have to send big data in parameter to my DLL (so i don't want to use files for communication because I need performance) and a DoWork is very fast (10 ms). I want to easily work in memory without sockets, windows messages queues, etc... and in the future, i will perhaps need custom synchronization between threads => multi-threading pattern is the best for me
Using many DLLs has several drawbacks:
A solution to the duplicate symbols problem is using LoadLibrary / GetProcAddress for every thread you create:
This can be a bad idea when the DLL you load will load another DLL. In this case wsock32 loads ws2_32.dll. Problematic:
In [1]: import ctypes
In [2]: k=ctypes.windll.kernel32
In [3]: a=k.LoadLibraryA('wsock32_1.dll')
In [4]: b=k.LoadLibraryA('wsock32_2.dll')
In [5]: a
Out[5]: 1885405184
In [6]: b
Out[6]: 1885339648
In [7]: k.GetProcAddress(a, "send")
Out[7]: 1980460801
In [8]: k.GetProcAddress(b, "send")
Out[8]: 1980460801
Here the send
loaded from separate copies of wsock32.dll
will just point to the same send function, because wsock32.dll is just a trampoline for ws2_32.dll.
However, you get different entry points for send, when you load ws2_32.
In [1]: import ctypes
In [2]: k=ctypes.windll.kernel32
In [3]: a=k.LoadLibraryA('ws2_32_1.dll')
In [4]: b=k.LoadLibraryA('ws2_32_2.dll')
In [5]: a
Out[5]: 1874853888
In [6]: b
Out[6]: 1874591744
In [7]: k.GetProcAddress(a, "send")
Out[7]: 1874882305
In [8]: k.GetProcAddress(b, "send")
Out[8]: 1874620161
Additional info: LoadLibrary loads a dll to the address space of the calling process. LoadLibrary remembers when you have already loaded a dll, so by using different dll names you can force loadlibrary to load the same dll to different places in the process address space.
A better solution would be to manually load the DLL code from memory, it can spare you the trouble of maintaining different copies of the same dll on disk.
http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With