pytorch - 💡(How to fix) Fix [Inductor] argmin/min returns incorrect indices for boolean tensors

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Fix Action

Fix / Workaround

CPU: Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 52 bits physical, 57 bits virtual Byte Order: Little Endian CPU(s): 64 On-line CPU(s) list: 0-63 Vendor ID: AuthenticAMD Model name: AMD EPYC 9334 32-Core Processor CPU family: 25 Model: 17 Thread(s) per core: 1 Core(s) per socket: 32 Socket(s): 2 Stepping: 1 Frequency boost: enabled CPU(s) scaling MHz: 96% CPU max MHz: 3910.2529 CPU min MHz: 1500.0000 BogoMIPS: 5400.52 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good amd_lbr_v2 nopl xtopology nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 hw_pstate ssbd mba perfmon_v2 ibrs ibpb stibp ibrs_enhanced vmmcall fsgsbase bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local avx512_bf16 clzero irperf xsaveerptr rdpru wbnoinvd amd_ppin cppc arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif x2avic v_spec_ctrl vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq la57 rdpid overflow_recov succor smca fsrm flush_l1d debug_swap L1d cache: 2 MiB (64 instances) L1i cache: 2 MiB (64 instances) L2 cache: 64 MiB (64 instances) L3 cache: 256 MiB (8 instances) NUMA node(s): 8 NUMA node0 CPU(s): 0-7 NUMA node1 CPU(s): 8-15 NUMA node2 CPU(s): 16-23 NUMA node3 CPU(s): 24-31 NUMA node4 CPU(s): 32-39 NUMA node5 CPU(s): 40-47 NUMA node6 CPU(s): 48-55 NUMA node7 CPU(s): 56-63 Vulnerability Gather data sampling: Not affected Vulnerability Indirect target selection: Not affected Vulnerability Itlb multihit: Not affected Vulnerability L1tf: Not affected Vulnerability Mds: Not affected Vulnerability Meltdown: Not affected Vulnerability Mmio stale data: Not affected Vulnerability Reg file data sampling: Not affected Vulnerability Retbleed: Not affected Vulnerability Spec rstack overflow: Mitigation; Safe RET Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization Vulnerability Spectre v2: Mitigation; Enhanced / Automatic IBRS; IBPB conditional; STIBP disabled; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected Vulnerability Srbds: Not affected Vulnerability Tsx async abort: Not affected

Code Example

import torch
device = 'cpu'

def fnmax(x):
    return x.max(0)
def fnmin(x):
    return x.min(0)

for n in range(1, 8):
    t1 = torch.randint(2, size=(n, 32), dtype=torch.bool, device=device)
    for desc, fn in [('min', fnmin)]:
        print(f"Testing {desc} {n=}...")
        eager = fn(t1)
        compiled = torch.compile(fn, backend='inductor')(t1)
        eager_values = [t1[j][i].item() for i, j in enumerate(eager.indices)]
        compiled_values = [t1[j][i].item() for i, j in enumerate(compiled.indices)]
        print("\tEager values:   ", eager_values)
        print("\tCompiled values:", compiled_values)
        check = "PASS" if eager.indices.tolist() == compiled.indices.tolist() else "FAIL"
        print(f"\t{check}")

---

Testing min n=1...
	Eager values:    [False, False, False, False, True, True, False, True, False, True, False, True, False, False, True, False, True, False, True, False, True, False, True, True, False, False, True, False, False, True, True, True]
	Compiled values: [False, False, False, False, True, True, False, True, False, True, False, True, False, False, True, False, True, False, True, False, True, False, True, True, False, False, True, False, False, True, True, True]
	PASS
Testing min n=2...
	Eager values:    [True, True, False, False, False, True, False, False, False, True, False, False, True, True, False, True, False, False, False, True, True, False, False, False, False, False, False, False, False, True, False, False]
	Compiled values: [True, True, True, False, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
	FAIL
Testing min n=3...
	Eager values:    [False, False, False, False, False, True, False, True, True, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, True, False]
	Compiled values: [True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, False, True, True, True, False, True, True, False]
	FAIL
Testing min n=4...
	Eager values:    [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
	Compiled values: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
	FAIL
Testing min n=5...
	Eager values:    [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
	Compiled values: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
	FAIL
Testing min n=6...
	Eager values:    [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
	Compiled values: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True]
	FAIL
Testing min n=7...
	Eager values:    [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False]
	Compiled values: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
	FAIL

---

import torch
import torch._dynamo

device = 'cpu'

def fn(x):
    return x.min(1, keepdim=True)[1]

mask = torch.randint(2, size=(4, 8, 32), dtype=torch.bool)

result_eager = fn(mask)
torch._dynamo.reset()
result_compiled = torch.compile(fn, backend='inductor')(mask)

e_item = result_eager[0, 0, 0].item()
c_item = result_compiled[0, 0, 0].item()
print(e_item, c_item, e_item == c_item)  # Outputs e.g. "1 0 False"
print(result_compiled)
print(result_eager)
print(f'Eager result: {result_eager[0, 0, 0].item()}')
print(f'Inductor result: {result_compiled[0, 0, 0].item()}')
RAW_BUFFERClick to expand / collapse

🐛 Describe the bug

This seems to be similar to #174069 fixed in #174076 so cc @jgong5 @mingfeima @XiaobingSuper @sanchitintel @ashokei @jingxu10 @jerryzh168 @aditew01 @chauhang @penguinwu @voznesenskym @EikanWang @Guobing-Chen @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @ipiszy @kadeng @muchulee8 @amjames @aakhundov @coconutruben @jataylo @Aminsed @jansel But it affects (also?) CPU.

I made a quick reproducer iterating over sizes:

import torch
device = 'cpu'

def fnmax(x):
    return x.max(0)
def fnmin(x):
    return x.min(0)

for n in range(1, 8):
    t1 = torch.randint(2, size=(n, 32), dtype=torch.bool, device=device)
    for desc, fn in [('min', fnmin)]:
        print(f"Testing {desc} {n=}...")
        eager = fn(t1)
        compiled = torch.compile(fn, backend='inductor')(t1)
        eager_values = [t1[j][i].item() for i, j in enumerate(eager.indices)]
        compiled_values = [t1[j][i].item() for i, j in enumerate(compiled.indices)]
        print("\tEager values:   ", eager_values)
        print("\tCompiled values:", compiled_values)
        check = "PASS" if eager.indices.tolist() == compiled.indices.tolist() else "FAIL"
        print(f"\t{check}")
<details><summary>Output</summary> <p> ``` Testing min n=1... Eager values: [False, False, False, False, True, True, False, True, False, True, False, True, False, False, True, False, True, False, True, False, True, False, True, True, False, False, True, False, False, True, True, True] Compiled values: [False, False, False, False, True, True, False, True, False, True, False, True, False, False, True, False, True, False, True, False, True, False, True, True, False, False, True, False, False, True, True, True] PASS Testing min n=2... Eager values: [True, True, False, False, False, True, False, False, False, True, False, False, True, True, False, True, False, False, False, True, True, False, False, False, False, False, False, False, False, True, False, False] Compiled values: [True, True, True, False, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True] FAIL Testing min n=3... Eager values: [False, False, False, False, False, True, False, True, True, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, True, False] Compiled values: [True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, False, True, True, True, False, True, True, False] FAIL Testing min n=4... Eager values: [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False] Compiled values: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True] FAIL Testing min n=5... Eager values: [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False] Compiled values: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True] FAIL Testing min n=6... Eager values: [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False] Compiled values: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True] FAIL Testing min n=7... Eager values: [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False] Compiled values: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True] FAIL ``` </p> </details>

What looks odd: It seems to start behaving like max instead of min.

It also works (i.e. fails) with a modified example from #174069 and random inputs:

import torch
import torch._dynamo

device = 'cpu'

def fn(x):
    return x.min(1, keepdim=True)[1]

mask = torch.randint(2, size=(4, 8, 32), dtype=torch.bool)

result_eager = fn(mask)
torch._dynamo.reset()
result_compiled = torch.compile(fn, backend='inductor')(mask)

e_item = result_eager[0, 0, 0].item()
c_item = result_compiled[0, 0, 0].item()
print(e_item, c_item, e_item == c_item)  # Outputs e.g. "1 0 False"
print(result_compiled)
print(result_eager)
print(f'Eager result: {result_eager[0, 0, 0].item()}')
print(f'Inductor result: {result_compiled[0, 0, 0].item()}')

I found that as the newly added test python test/inductor/test_torchinductor.py CpuTests.test_max_min_bool_cpu fails for me

Versions

PyTorch version: 2.12.0+cu130 Is debug build: False CUDA used to build PyTorch: 13.0 ROCM used to build PyTorch: N/A

OS: Rocky Linux 9.6 (Blue Onyx) (x86_64) GCC version: (GCC) 14.3.0 Clang version: Could not collect CMake version: Could not collect Libc version: glibc-2.34

Python version: 3.13.5 (main, Jul 30 2025, 17:50:55) [GCC 14.3.0] (64-bit runtime) Python platform: Linux-5.14.0-570.49.1.el9_6.x86_64-x86_64-with-glibc2.34 Is CUDA available: True CUDA runtime version: Could not collect CUDA_MODULE_LOADING set to: GPU models and configuration: GPU 0: NVIDIA H100 GPU 1: NVIDIA H100 GPU 2: NVIDIA H100 GPU 3: NVIDIA H100

Nvidia driver version: 580.159.04 cuDNN version: Could not collect Is XPU available: False HIP runtime version: N/A MIOpen runtime version: N/A Is XNNPACK available: True Caching allocator config: N/A

CPU: Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 52 bits physical, 57 bits virtual Byte Order: Little Endian CPU(s): 64 On-line CPU(s) list: 0-63 Vendor ID: AuthenticAMD Model name: AMD EPYC 9334 32-Core Processor CPU family: 25 Model: 17 Thread(s) per core: 1 Core(s) per socket: 32 Socket(s): 2 Stepping: 1 Frequency boost: enabled CPU(s) scaling MHz: 96% CPU max MHz: 3910.2529 CPU min MHz: 1500.0000 BogoMIPS: 5400.52 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good amd_lbr_v2 nopl xtopology nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 hw_pstate ssbd mba perfmon_v2 ibrs ibpb stibp ibrs_enhanced vmmcall fsgsbase bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local avx512_bf16 clzero irperf xsaveerptr rdpru wbnoinvd amd_ppin cppc arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif x2avic v_spec_ctrl vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq la57 rdpid overflow_recov succor smca fsrm flush_l1d debug_swap L1d cache: 2 MiB (64 instances) L1i cache: 2 MiB (64 instances) L2 cache: 64 MiB (64 instances) L3 cache: 256 MiB (8 instances) NUMA node(s): 8 NUMA node0 CPU(s): 0-7 NUMA node1 CPU(s): 8-15 NUMA node2 CPU(s): 16-23 NUMA node3 CPU(s): 24-31 NUMA node4 CPU(s): 32-39 NUMA node5 CPU(s): 40-47 NUMA node6 CPU(s): 48-55 NUMA node7 CPU(s): 56-63 Vulnerability Gather data sampling: Not affected Vulnerability Indirect target selection: Not affected Vulnerability Itlb multihit: Not affected Vulnerability L1tf: Not affected Vulnerability Mds: Not affected Vulnerability Meltdown: Not affected Vulnerability Mmio stale data: Not affected Vulnerability Reg file data sampling: Not affected Vulnerability Retbleed: Not affected Vulnerability Spec rstack overflow: Mitigation; Safe RET Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization Vulnerability Spectre v2: Mitigation; Enhanced / Automatic IBRS; IBPB conditional; STIBP disabled; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected Vulnerability Srbds: Not affected Vulnerability Tsx async abort: Not affected

Versions of relevant libraries: [pip3] numpy==2.3.2 [pip3] nvidia-cublas==13.1.0.3 [pip3] nvidia-cublas-cu12==12.6.4.1 [pip3] nvidia-cuda-cupti==13.0.85 [pip3] nvidia-cuda-cupti-cu12==12.6.80 [pip3] nvidia-cuda-nvrtc==13.0.88 [pip3] nvidia-cuda-nvrtc-cu12==12.6.77 [pip3] nvidia-cuda-runtime==13.0.96 [pip3] nvidia-cuda-runtime-cu12==12.6.77 [pip3] nvidia-cudnn-cu12==9.5.1.17 [pip3] nvidia-cudnn-cu13==9.20.0.48 [pip3] nvidia-cufft==12.0.0.61 [pip3] nvidia-cufft-cu12==11.3.0.4 [pip3] nvidia-curand==10.4.0.35 [pip3] nvidia-curand-cu12==10.3.7.77 [pip3] nvidia-cusolver==12.0.4.66 [pip3] nvidia-cusolver-cu12==11.7.1.2 [pip3] nvidia-cusparse==12.6.3.3 [pip3] nvidia-cusparse-cu12==12.5.4.2 [pip3] nvidia-cusparselt-cu12==0.6.3 [pip3] nvidia-cusparselt-cu13==0.8.1 [pip3] nvidia-nccl-cu12==2.26.2 [pip3] nvidia-nccl-cu13==2.29.7 [pip3] nvidia-nvjitlink==13.0.88 [pip3] nvidia-nvjitlink-cu12==12.6.85 [pip3] nvidia-nvtx==13.0.85 [pip3] nvidia-nvtx-cu12==12.6.77 [pip3] torch==2.12.0 [pip3] triton==3.7.0 [conda] Could not collect

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

pytorch - 💡(How to fix) Fix [Inductor] argmin/min returns incorrect indices for boolean tensors