[Mlir-commits] [mlir] [mlir][python] Allow contexts to be created with a custom thread pool. (PR #72042)

Stella Laurenzo llvmlistbot at llvm.org
Sat Nov 11 17:25:42 PST 2023


https://github.com/stellaraccident created https://github.com/llvm/llvm-project/pull/72042

The existing initialization sequence always enables multi-threading at MLIRContext construction time, making it impractical to provide a customized thread pool.

Here, this is changed to always create the context with threading disabled, process all site-specific init hooks (which can set thread pools) and ultimately enable multi-threading unless if site-configured to not do so.

This should preserve the existing user-visible initialization behavior while also letting downstreams ensure that contexts are always created with a shared thread pool. This was tested with IREE, which has such a concept. Using site-specific thread tuning produced up to 2x single compilation job behavior and customization of batch compilation (i.e. as part of a build system) to utilize half the memory and run the entire test suite ~2x faster. Given this, I believe that the additional configurability can well pay for itself for implementations that use it. We may also want to present user-level Python APIs for controlling threading configuration in the future.

>From 4102d0904c4adfe4992bfc57c117d05abb286778 Mon Sep 17 00:00:00 2001
From: Stella Laurenzo <stellaraccident at gmail.com>
Date: Sat, 11 Nov 2023 17:14:41 -0800
Subject: [PATCH] [mlir][python] Allow contexts to be created with a custom
 thread pool.

The existing initialization sequence always enables multi-threading at MLIRContext construction time, making it impractical to provide a customized thread pool.

Here, this is changed to always create the context with threading disabled, process all site-specific init hooks (which can set thread pools) and ultimately enable multi-threading unless if site-configured to not do so.

This should preserve the existing user-visible initialization behavior while also letting downstreams ensure that contexts are always created with a shared thread pool. This was tested with IREE, which has such a concept. Using site-specific thread tuning produced up to 2x single compilation job behavior and customization of batch compilation (i.e. as part of a build system) to utilize half the memory and run the entire test suite ~2x faster. Given this, I believe that the additional configurability can well pay for itself for implementations that use it. We may also want to present user-level Python APIs for controlling threading configuration in the future.
---
 mlir/lib/Bindings/Python/IRCore.cpp     |  2 +-
 mlir/python/mlir/_mlir_libs/__init__.py | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Bindings/Python/IRCore.cpp b/mlir/lib/Bindings/Python/IRCore.cpp
index 0f2ca666ccc050e..745aa64e63b67d4 100644
--- a/mlir/lib/Bindings/Python/IRCore.cpp
+++ b/mlir/lib/Bindings/Python/IRCore.cpp
@@ -597,7 +597,7 @@ py::object PyMlirContext::createFromCapsule(py::object capsule) {
 }
 
 PyMlirContext *PyMlirContext::createNewContextForInit() {
-  MlirContext context = mlirContextCreate();
+  MlirContext context = mlirContextCreateWithThreading(false);
   return new PyMlirContext(context);
 }
 
diff --git a/mlir/python/mlir/_mlir_libs/__init__.py b/mlir/python/mlir/_mlir_libs/__init__.py
index d5fc447e49bf3a6..6ce77b4cb93f609 100644
--- a/mlir/python/mlir/_mlir_libs/__init__.py
+++ b/mlir/python/mlir/_mlir_libs/__init__.py
@@ -46,6 +46,13 @@ def get_include_dirs() -> Sequence[str]:
 #   c. If the module has a 'context_init_hook', it will be added to a list
 #     of callbacks that are invoked as the last step of Context
 #     initialization (and passed the Context under construction).
+#   d. If the module has a 'disable_multithreading' attribute, it will be
+#     taken as a boolean. If it is True for any initializer, then the
+#     default behavior of enabling multithreading on the context
+#     will be suppressed. This complies with the original behavior of all
+#     contexts being created with multithreading enabled while allowing
+#     this behavior to be changed if needed (i.e. if a context_init_hook
+#     explicitly sets up multithreading).
 #
 # This facility allows downstreams to customize Context creation to their
 # needs.
@@ -58,8 +65,10 @@ def _site_initialize():
     logger = logging.getLogger(__name__)
     registry = ir.DialectRegistry()
     post_init_hooks = []
+    disable_multithreading = False
 
     def process_initializer_module(module_name):
+        nonlocal disable_multithreading
         try:
             m = importlib.import_module(f".{module_name}", __name__)
         except ModuleNotFoundError:
@@ -79,6 +88,10 @@ def process_initializer_module(module_name):
         if hasattr(m, "context_init_hook"):
             logger.debug("Adding context init hook from %r", m)
             post_init_hooks.append(m.context_init_hook)
+        if hasattr(m, "disable_multithreading"):
+            if bool(m.disable_multithreading):
+                logger.debug("Disabling multi-threading for context")
+                disable_multithreading = True
         return True
 
     # If _mlirRegisterEverything is built, then include it as an initializer
@@ -100,6 +113,8 @@ def __init__(self, *args, **kwargs):
             self.append_dialect_registry(registry)
             for hook in post_init_hooks:
                 hook(self)
+            if not disable_multithreading:
+                self.enable_multithreading(True)
             # TODO: There is some debate about whether we should eagerly load
             # all dialects. It is being done here in order to preserve existing
             # behavior. See: https://github.com/llvm/llvm-project/issues/56037



More information about the Mlir-commits mailing list