arrayfire / arrayfire-dotnet

.NET wrapper for ArrayFire
BSD 3-Clause "New" or "Revised" License
78 stars 21 forks source link

OpenCL dll load error in HelloWorld #5

Closed gualandri43 closed 8 years ago

gualandri43 commented 8 years ago

Submitting per Pavan's request from ArrayFire Google Group:

I found the .NET wrapper on Github and downloaded the files. I am able to get the example HelloWorld project to run correctly. However, when I tried to modify the HelloWorld code to use OpenCL instead of the CPU backend, I encountered the below error:

Unhandled Exception: ArrayFire.ArrayFireException: Failed to load dynamic library

Is it some sort of missing reference problem?

My graphics card software lists that the OpenCL driver is installed. Also, when I run example file 'getting_started\vectorize' from the typical C++ files, I get a Bonaire device and an Intel device listed on my console output when compiling the executable using the OpenCL configuration option in Visual Studio.

For reference, my system has a i7 3770K CPU with a AMD Radeon HD 7790 1GB card.

royalstream commented 8 years ago

Hi,

The .NET wrapper is currently accessing the unified dynamic library af.dll which is just a "gateway" library that calls afcpu.dll, afopencl.dll or afcuda.dll depending on whether you're targeting the CPU, OpenCL or CUDA respectively.

If HelloWorld works correctly for you using the CPU I have to assume that afcpu.dll was loaded correctly so there's no reason why loading afopencl.dll should fail (as far as the .NET wrapper goes).

This means that to help you I may need a hand from the official ArrayFire developers because this could be outside my reach. I do remember having some small issues a while back with OpenCL because it was picking my Intel CPU before my video card as the OpenCL device.

That said, in the meantime, I'll try my best to help.

At what specific call do you get the exception?

Also, can you try the following:

9prady9 commented 8 years ago

@gualandri43 The list of devices sounds correct, 7790 is bonarie and the other device is your CPU.

All the dependencies of the library has to be satisfied for the dll loading to be successful. If even one of the dependencies is missing, the loading stage fails and hence the exception you are seeing.

What @royalstream pointed are essentially the things you need to make sure to use the gateway dll (I have to say, i like the sound of that :))

If dll loading failed, then it is most likely the first ArrayFire function call or operation would throw that exception due to deficiency of required dll symbols.

One way to verify if all the dependencies are available on your system is to use dependency walker on the program and see which dlls are missing from PATH.

Repeating what @royalstream said again:

To narrow down the issue, you can run examples installed by the ArrayFire installer and see if they are running since they also use the gateway dll.

shehzan10 commented 8 years ago

From @royalstream

This is what I've found on my system:

If I put a pause before the program is about to end ("Press any key to continue") I reach this point with no errors. This leads me to think the problem is related to unloading the DLL. If I don't use the debugger and stick to OpenCL only, I get no errors. Do you get the same behavior?

No, on the contrary, what I am observing is quite the opposite. The behavior looks like its a loading failure because it happens at setBackend. I get failure irrepective of debugger and release/debug

royalstream commented 8 years ago

I will create a minimal C# app that simply calls setBackend, prints the device info and quits without using my library, something really minimal and we can take it from there.

royalstream commented 8 years ago

Here it is: https://github.com/royalstream/minimal-setbackend

It doesn't use any libraries, just a plain vainilla wrapper.

shehzan10 commented 8 years ago

Ok, I'm not sure if this is replicated in the wrapper, but AF_BACKEND_OPENCL is 4 not 3. The backends increase in powers of 2.

Once I fixed this in the minimal setbackend project, OpenCL worked fine.

shehzan10 commented 8 years ago

Yup, thats the issue https://github.com/arrayfire/arrayfire-dotnet/blob/devel/Wrapper/Interop/enums.cs#L292

shehzan10 commented 8 years ago

Good work on that minimal project. Narrowed it down.

I think OpenCL was working for you when you didn't run CUDA/CPU because OpenCL was the default backend (and you didn't have CUDA available). So when the unified library was loaded, OpenCL got loaded. So if you called setBackend(3), it didnt really do anything and just keep the OpenCL backend active.

That's what happened in the minimal project when I ran it on an AMD machine. It failed the first setBackend operation and then ran OpenCL just fine. On a NVIDIA machine, it failed the setBackend(OpenCL), but ran CUDA fine. That's how I deduced that the enum was the issue.

royalstream commented 8 years ago

The enums values get generated automatically from the C headers. But I have not regenerated them in quite a while. It looks like the value was 3 at some point.

I re-ran the AutoGenTool on the latest headers and the value is now four.

I will commit the changes in a few seconds.

shehzan10 commented 8 years ago

Yes it was 3 to begin with, but we updated it to 4 before releasing v3.2 final.

royalstream commented 8 years ago

And I never re-ran the AutoGenTool on the new headers. My bad.

royalstream commented 8 years ago

It's committed on the PR now.

shehzan10 commented 8 years ago

Fixed by #7