Skip to content

CPU multi threading doesn't work on Intel's hybrid core architecture #24761

Description

@DDoSolitary

What happened?

Running iree-benchmark-module on i7-13700 shows that wall time equals cpu time, indicating only a single thread is used.

> iree-benchmark-module --module=model.vmfb --device=local-task --function=torch-jit-export --input=@in.npy
2026-07-26T22:48:03+08:00
Running /data/models/.venv/lib/python3.13/site-packages/iree/_runtime_libs/iree-benchmark-module
Run on (24 X 5100 MHz CPU s)
CPU Caches:
  L1 Data 48 KiB (x12)
  L1 Instruction 32 KiB (x12)
  L2 Unified 2048 KiB (x12)
  L3 Unified 30720 KiB (x1)
Load Average: 0.19, 0.13, 0.15
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
***WARNING*** ASLR is enabled, the results may have unreproducible noise in them.
-----------------------------------------------------------------------------------------------------
Benchmark                                           Time             CPU   Iterations UserCounters...
-----------------------------------------------------------------------------------------------------
BM_torch-jit-export/process_time/real_time        422 ms          422 ms            2 items_per_second=2.36932/s

While on an older platform multi threading works as expected:

Working Directory: /data/models/build/models/example
Test timeout computed to be: 10000000
2026-07-26T08:05:47+00:00
Running /data/models/.venv/lib/python3.13/site-packages/iree/_runtime_libs/iree-benchmark-module
Run on (16 X 2593.91 MHz CPU s)
CPU Caches:
  L1 Data 48 KiB (x16)
  L1 Instruction 32 KiB (x16)
  L2 Unified 1280 KiB (x16)
  L3 Unified 43008 KiB (x1)
Load Average: 0.43, 0.27, 0.20
***WARNING*** ASLR is enabled, the results may have unreproducible noise in them.
-----------------------------------------------------------------------------------------------------
Benchmark                                           Time             CPU   Iterations UserCounters...
-----------------------------------------------------------------------------------------------------
BM_torch-jit-export/process_time/real_time        111 ms         1182 ms            6 items_per_second=8.99493/s

Root-cause

  1. The sysfs-based topology detection code incorrectly uses cluster_id as a synonym of NUMA node id/isolates the clusters
    Exacerbated by
  2. By default, only the "current" NUMA node is utilized (--task_topology_nodes defaults to "current" vs. "all")
  3. cluster_ids are not continuous, leading to a latent failure in enumeration (task_topology_nodes "all" cannot be used as a workaround)

The sysfs-based topology detection

for (uint32_t cpu = 0; cpu < processor_count; ++cpu) {
uint32_t cluster_id = 0;
if (iree_sysfs_try_query_cluster_id(cpu, &cluster_id) &&
iree_sysfs_is_valid_cluster(cluster_id)) {
if (!CPU_ISSET(cluster_id, &cluster_set)) {
CPU_SET(cluster_id, &cluster_set);
++unique_clusters;
}
}
}

For example, on a i7-13700 there's a total of 10 clusters with 8 P-cores = 8 clusters and 8 E-cores = 2 clusters:
every P-core forms its own cluster while groups of E-cores form other clusters

> grep . /sys/devices/system/cpu/cpu*/topology/cluster_id | sort -t: -k2 -n                                                                                                                                                                              
/sys/devices/system/cpu/cpu0/topology/cluster_id:0
/sys/devices/system/cpu/cpu1/topology/cluster_id:0
/sys/devices/system/cpu/cpu2/topology/cluster_id:8
/sys/devices/system/cpu/cpu3/topology/cluster_id:8
/sys/devices/system/cpu/cpu4/topology/cluster_id:16
/sys/devices/system/cpu/cpu5/topology/cluster_id:16
/sys/devices/system/cpu/cpu6/topology/cluster_id:24
/sys/devices/system/cpu/cpu7/topology/cluster_id:24
/sys/devices/system/cpu/cpu8/topology/cluster_id:32
/sys/devices/system/cpu/cpu9/topology/cluster_id:32
/sys/devices/system/cpu/cpu10/topology/cluster_id:40
/sys/devices/system/cpu/cpu11/topology/cluster_id:40
/sys/devices/system/cpu/cpu12/topology/cluster_id:48
/sys/devices/system/cpu/cpu13/topology/cluster_id:48
/sys/devices/system/cpu/cpu14/topology/cluster_id:56
/sys/devices/system/cpu/cpu15/topology/cluster_id:56
/sys/devices/system/cpu/cpu16/topology/cluster_id:64
/sys/devices/system/cpu/cpu17/topology/cluster_id:64
/sys/devices/system/cpu/cpu18/topology/cluster_id:64
/sys/devices/system/cpu/cpu19/topology/cluster_id:64
/sys/devices/system/cpu/cpu20/topology/cluster_id:72
/sys/devices/system/cpu/cpu21/topology/cluster_id:72
/sys/devices/system/cpu/cpu22/topology/cluster_id:72
/sys/devices/system/cpu/cpu23/topology/cluster_id:72

Removing the cluster_id code and fallback to physical_package_id, performance is immediately back to normal:

diff --git a/runtime/src/iree/task/topology_sysfs.c b/runtime/src/iree/task/topology_sysfs.c
index 083f014408..dfd00c1d76 100644
--- a/runtime/src/iree/task/topology_sysfs.c
+++ b/runtime/src/iree/task/topology_sysfs.c
@@ -141,11 +141,11 @@ static bool iree_sysfs_try_query_cluster_id(uint32_t processor,
   char path[256];

   // Try cluster_id first (kernel 5.16+).
-  iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/cluster_id",
-                iree_sysfs_get_root_path(), processor);
-  if (iree_sysfs_try_read_uint32(path, out_cluster_id)) {
-    return true;
-  }
+  // iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/cluster_id",
+  //               iree_sysfs_get_root_path(), processor);
+  // if (iree_sysfs_try_read_uint32(path, out_cluster_id)) {
+  //   return true;
+  // }

   // Fallback to physical_package_id (socket/package).
   iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/physical_package_id",
2026-07-26T23:11:20+08:00
Running ./build/tools/iree-benchmark-module
Run on (24 X 5100 MHz CPU s)
CPU Caches:
  L1 Data 48 KiB (x12)
  L1 Instruction 32 KiB (x12)
  L2 Unified 2048 KiB (x12)
  L3 Unified 30720 KiB (x1)
Load Average: 4.91, 1.29, 0.52
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
***WARNING*** ASLR is enabled, the results may have unreproducible noise in them.
-----------------------------------------------------------------------------------------------------
Benchmark                                           Time             CPU   Iterations UserCounters...
-----------------------------------------------------------------------------------------------------
BM_torch-jit-export/process_time/real_time       63.9 ms          709 ms            9 items_per_second=15.6597/s

Note: physical_package_id is not NUMA node id either, there is /sys/devices/system/node/node*/cpumap.

#22455 #8469

What component(s) does this issue relate to?

Runtime

Version information

compiler and runtime are manually built on git commit bc908fd

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🐞Something isn't workinghal/cpuRuntime Host/CPU-based HAL backendregressionMarks regression of feature, compatibility or performance

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions