eschnett / mpi-hs

MPI bindings for Haskell
Other
16 stars 3 forks source link

Cannot build when using MPICH on Linux #1

Closed dsorokin closed 5 years ago

dsorokin commented 5 years ago

Hi! I cannot build mpi-hs from master when trying to use MPICH 3.3 on Linux Mint 19:

Preprocessing library for mpi-hs-0.5.1.2..
Building library for mpi-hs-0.5.1.2..
[2 of 5] Compiling Control.Distributed.MPI ( dist/build/Control/Distributed/MPI.hs, dist/build/Control/Distributed/MPI.o )

lib/Control/Distributed/MPI.chs:1529:17: error:
    • Couldn't match expected type ‘CInt’ with actual type ‘Ptr b0’
    • In the first argument of ‘requestGetStatusBool_’, namely
        ‘(castPtr req')’
      In a stmt of a 'do' block:
        _ <- requestGetStatusBool_ (castPtr req') flag st'
      In the expression:
        do _ <- requestGetStatusBool_ (castPtr req') flag st'
           b <- peekBool flag
           return (b, st)
     |
1529 |                (castPtr req') flag st'
     |                 ^^^^^^^^^^^^

lib/Control/Distributed/MPI.chs:1560:12: error:
    • Couldn't match expected type ‘CInt’ with actual type ‘Ptr b1’
    • In the first argument of ‘requestGetStatus__’, namely
        ‘(castPtr req')’
      In a stmt of a 'do' block:
        _ <- requestGetStatus__ (castPtr req') flag st
      In the expression:
        do _ <- requestGetStatus__ (castPtr req') flag st
           peekBool flag
     |
1560 |           (castPtr req') flag st
     |            ^^^^^^^^^^^^

Is it required to use stack only? I tried to build by using cabal and GHC 8.6.5.

Thanks, David

eschnett commented 5 years ago

No, Stack is not required.

The error message looks as if the type of the C function MPI_Request_get_status was deduced wrong. This is done by the tool c2hs.

Can you look for the auto-generated file MPI.hs in your directory tree? This file is generated from MPI.chs. For me (using Stack), this file is located at ./.stack-work/dist/x86_64-osx/Cabal-2.4.0.1/build/Control/Distributed/MPI.hs. The command find . -name MPI.hs might help you.

In this file I see the line

foreign import ccall safe "Control/Distributed/MPI.chs.h MPI_Request_get_status"
  requestGetStatusBool_ :: ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr C2HSImp.CInt) -> ((C2HSImp.Ptr (Status)) -> (IO C2HSImp.CInt))))

If you see something different there – in particular, if the second argument is not a Ptr – please let me know.

dsorokin commented 5 years ago

Yes, I see a different line:

foreign import ccall safe "Control/Distributed/MPI.chs.h MPI_Request_get_status"
  requestGetStatusBool_ :: (C2HSImp.CInt -> ((C2HSImp.Ptr C2HSImp.CInt) -> ((C2HSImp.Ptr (Status)) -> (IO C2HSImp.CInt))))

P.S. This is still not master. This is the latest release mpi-hs-0.5.1.2, where I added two lines to the cabal file so that GHC could find the MPICH headers and libraries.

dsorokin commented 5 years ago

Also I looked at the definition of the mpi.h file for MPICH:

/* MPI request opjects */
typedef int MPI_Request;

...

int MPI_Request_get_status(MPI_Request request, int *flag, MPI_Status *status) MPICH_API_PUBLIC;
eschnett commented 5 years ago

I see. That explains the error message...

I'm unsure how to handle this. It's certainly possible with a bit of #ifdef magic, but maybe there's a more elegant way. I hope that I'll have a solution within a few days.

PS: It should not be necessary to modify the *.cabal file; there should also be a command line option when calling cabal or ghc to pass the extra include directories. Of course, modifying the *.cabal file works fine.

dsorokin commented 5 years ago

It would be fine if such a mechansim could work with third-party hardware MPI implementations as well. MPICH is just an example.

eschnett commented 5 years ago

Yes. Unfortunately, the MPI standard doesn't define whether MPI_Request needs to be a new type, or whether it can be a typedef. c2hs makes a distinction between these two.

To catch all these inconsistencies, we'll have to test with all the common MPI implementations. You might have seen that I am currently using CircleCI for this, but I'm at the moment only testing with OpenMPI. I will need to add other test jobs for MPICH and mvapich at least, and possibly also for Intel MPI if their licence permits this.

eschnett commented 5 years ago

Good things come to those who wait. There is now a new release (0.5.2.0) on Hackage that works with MPICH as well (and with all other MPI implementations, I hope).

My previous implementation was too complicated – it looked into the internal representation of MPI_Request, which happened to be a pointer in OpenMPI, and represented these as ForeignPtr. Of course, MPI_Request is just an opaque type, and one just needs to store the respective bit pattern instead. The code is now simpler. Thank you.

dsorokin commented 5 years ago

Thanks! I confirm from my side that I could build your package too. Please close the issue as solved.