Skip to content

MPI detection: support Intel MPI on Windows #14518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

dalcinl
Copy link

@dalcinl dalcinl commented Apr 27, 2025

This pull request enhances the MPI dependency handling in the Meson build system by introducing support for Intel MPI on Windows. Below are the most important changes:

New Feature: Intel MPI Support on Windows

  • Added a new IMPIDependency class to handle Intel MPI on Windows AMD64, including logic for locating the installation directory via the I_MPI_ROOT environment variable, and validating the presence of required headers and libraries (mpi.h and impi.lib).

Platform-Specific Adjustments

  • Modified the mpi_factory logic to ensure that the CONFIG_TOOL method is not used on Windows. Microsoft MPI does not use compiler wrappers. The Intel MPI compiler wrappers are implemented as batch files, and I'm not sure how to invoke them. As far as I can tell, the logic to detect and query mpicc and friends on Windows does not work for either MSMPI or IMPI, so better to disable for the time being.

DISCLAIMER: description generated with GitHub Copilot and adjusted manually by a (supposedly) sentient being.

@dalcinl dalcinl requested a review from jpakkane as a code owner April 27, 2025 08:00
@dalcinl
Copy link
Author

dalcinl commented Apr 27, 2025

Here you have build logs of this PR being used to build mpi4py with Intel MPI on Windows.

buildtype = env.coredata.optstore.get_value_for(OptionKey('buildtype'))
assert isinstance(buildtype, str)
libdir_post = 'debug' if buildtype.startswith('debug') else 'release'
for subdirs in (['mpi', libdir_post], [libdir_post]):
libdir_buildtype = os.path.join(libdir, *subdirs)
if os.path.isdir(libdir_buildtype):
libdir = libdir_buildtype
break
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block may look a bit convoluted. The intention here is to cope with various install directory layouts that Intel MPI has used across releases and distribution methods (offline installer, nuget, pip/conda packages).

@eli-schwartz
Copy link
Member

DISCLAIMER: description generated with GitHub Copilot

I could tell, because it was impossible to read...

and adjusted manually by a (supposedly) sentient being.

... and this helped, but not enough.

Comment on lines +281 to +276
buildtype = env.coredata.optstore.get_value_for(OptionKey('buildtype'))
assert isinstance(buildtype, str)
libdir_post = 'debug' if buildtype.startswith('debug') else 'release'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly is the difference between these two directories? Is this about which microsoft CRT the respective libraries are compiled with?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intel MPI provides different import libraries for debug vs release builds. Depending on the Intel MPI version and/or how you get the Intel MPI binaries, these directories are or are not present.
The latest releases of Intel MPI use <libdir>/mpi/debug for the debug import libraries, and `/ for the release import libraries.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you guys do not want this mess, I can just kill the whole block. This would mean that for recent versions of Intel MPI we will always get what the Intel folks label as "release" build.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I'm asking is because the release type is unrelated to the CRT except inasmuch as the buildtype can be used to automatically set the CRT. See b_vscrt from https://mesonbuild.com/Builtin-options.html#base-options

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I do not have enough Windows nor Meson expertise to properly answer your question. AFAICT, Intel MPI ships debug and release import libraries and DLLs.

$ cd "$I_MPI_ROOT"

$ find . -name 'impi.lib'
./lib/impi.lib
./lib/mpi/debug/impi.lib

$ find . -name 'impi.dll'
./bin/impi.dll
./bin/mpi/debug/impi.dll

Does the following output (from MinGW) give you any hints?

$ ldd ./bin/impi.dll
        ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x7ff98b7e0000)
        KERNEL32.DLL => /c/Windows/System32/KERNEL32.DLL (0x7ff98b430000)
        KERNELBASE.dll => /c/Windows/System32/KERNELBASE.dll (0x7ff989090000)
        msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ff98ad30000)
        WS2_32.dll => /c/Windows/System32/WS2_32.dll (0x7ff98a180000)
        RPCRT4.dll => /c/Windows/System32/RPCRT4.dll (0x7ff98b260000)
        ADVAPI32.dll => /c/Windows/System32/ADVAPI32.dll (0x7ff98b500000)
        sechost.dll => /c/Windows/System32/sechost.dll (0x7ff98b380000)
        imagehlp.dll => /c/Windows/System32/imagehlp.dll (0x7ff98b5c0000)
        ucrtbase.dll => /c/Windows/System32/ucrtbase.dll (0x7ff988de0000)

$ ldd ./bin/mpi/debug/impi.dll                                                  
        ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x7ff98b7e0000)
        KERNEL32.DLL => /c/Windows/System32/KERNEL32.DLL (0x7ff98b430000)
        KERNELBASE.dll => /c/Windows/System32/KERNELBASE.dll (0x7ff989090000)
        msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ff98ad30000)
        WS2_32.dll => /c/Windows/System32/WS2_32.dll (0x7ff98a180000)
        RPCRT4.dll => /c/Windows/System32/RPCRT4.dll (0x7ff98b260000)
        ADVAPI32.dll => /c/Windows/System32/ADVAPI32.dll (0x7ff98b500000)
        sechost.dll => /c/Windows/System32/sechost.dll (0x7ff98b380000)
        dbghelp.dll => /c/Windows/SYSTEM32/dbghelp.dll (0x7ff954e40000)
        ucrtbase.dll => /c/Windows/System32/ucrtbase.dll (0x7ff988de0000)
        dbgcore.DLL => /c/Windows/SYSTEM32/dbgcore.DLL (0x7ff97bf00000)
        combase.dll => /c/Windows/System32/combase.dll (0x7ff989690000)
        OLEAUT32.dll => /c/Windows/System32/OLEAUT32.dll (0x7ff989aa0000)
        msvcp_win.dll => /c/Windows/System32/msvcp_win.dll (0x7ff988bc0000)

Copy link
Author

@dalcinl dalcinl Apr 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran nm -P on the two import libraries. AFAICT, they only differ in a bunch of extra symbols related to debugging. These symbols are definitely not part of the MPI standard, they are not even declared in the header mpi.h. All this seems to indicate that for most practical purposes, building with the release build impi.lib is good enough, and users may be able to switch at runtime (via PATH) to load the debug build impi.dll if ever needed.

Long story short, I believe I can just remove all this debug vs release logic, and just set libdir = rootdir/lib. Thoughts?

$ diff  debug.txt release.txt | grep __imp_
> __imp_MPIR_Breakpoint I 0 
> __imp_MPIR_being_debugged I 0 
> __imp_MPIR_debug_abort_string I 0 
> __imp_MPIR_debug_gate I 0 
> __imp_MPIR_debug_state I 0 
> __imp_MPIR_proctable I 0 
> __imp_MPIR_proctable_size I 0 
> __imp_mqs_destroy_image_info I 0 
> __imp_mqs_destroy_process_info I 0 
> __imp_mqs_dll_error_string I 0 
> __imp_mqs_dll_taddr_width I 0 
> __imp_mqs_get_communicator I 0 
> __imp_mqs_image_has_queues I 0 
> __imp_mqs_next_communicator I 0 
> __imp_mqs_next_operation I 0 
> __imp_mqs_process_has_queues I 0 
> __imp_mqs_setup_basic_callbacks I 0 
> __imp_mqs_setup_communicator_iterator I 0 
> __imp_mqs_setup_image I 0 
> __imp_mqs_setup_operation_iterator I 0 
> __imp_mqs_setup_process I 0 
> __imp_mqs_update_communicator_list I 0 
> __imp_mqs_version_compatibility I 0 
> __imp_mqs_version_string I 0 

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After more digging, I can confirm that we can build with the release import library, and then at runtime we can load (either via PATH or AddDLLDirectory) either the release or debug library.

This is an excerpt of mpi4py CI runs on GitHub Actions. In each cases, mpi4py loads the impi.dll library (via os.add_dll_directory) from the debug directory or the (default) release one.

full debug-lib logs

run:
  mpiexec -n 1 python -m mpi4py --mpi-library
  mpiexec -n 2 python -m mpi4py.bench helloworld
  mpiexec -n [3](https://github.com/mpi4py/mpi4py/actions/runs/14716202975/job/41300036438#step:18:3) python -m mpi4py.bench ringtest
  shell: C:\Program Files\PowerShell\7\pwsh.EXE -command ". '{0}'"
env:
    ...
    I_MPI_LIBRARY_KIND: debug
output:
C:\Program Files (x86)\Intel\oneAPI\mpi\2021.15\bin\mpi\debug\impi.dll
Hello, World! I am process 0 of 2 on fv-az1402-432.
Hello, World! I am process 1 of 2 on fv-az1402-432.
time for 1 loops = 0.0001021 seconds (3 processes, 1 bytes)

full release-lib logs

run:
  mpiexec -n 1 python -m mpi4py --mpi-library
  mpiexec -n 2 python -m mpi4py.bench helloworld
  mpiexec -n 3 python -m mpi4py.bench ringtest
  shell: C:\Program Files\PowerShell\7\pwsh.EXE -command ". '{0}'"
env:
    I_MPI_LIBRARY_KIND: release
output:
C:\Program Files (x86)\Intel\oneAPI\mpi\2021.15\bin\impi.dll
Hello, World! I am process 0 of 2 on fv-az1402-432.
Hello, World! I am process 1 of 2 on fv-az1402-432.
time for 1 loops = 0.0001186 seconds (3 processes, 1 bytes)

@dalcinl dalcinl force-pushed the impi-windows branch 3 times, most recently from 8bc6529 to f3f91e5 Compare April 27, 2025 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants