Skip to content

Fix MT read memory limit defaulting to wrong size when off-heap limit is disabled - #14507

Merged
zpuller merged 2 commits into
NVIDIA:mainfrom
zpuller:mt_read_limits
Apr 7, 2026
Merged

Fix MT read memory limit defaulting to wrong size when off-heap limit is disabled#14507
zpuller merged 2 commits into
NVIDIA:mainfrom
zpuller:mt_read_limits

Conversation

@zpuller

@zpuller zpuller commented Apr 1, 2026

Copy link
Copy Markdown
Collaborator

Fixes #14292.

Description

When spark.rapids.memory.host.offHeapLimit.enabled is false (the default),
getPinnedPoolAndOffHeapLimits returns -1 for the non-pinned limit (meaning unlimited).
The code that sets the default MT read memory limit was using this -1 literally:

(0.9 * (pinnedSize + nonPinnedLimit)).toLong  // nonPinnedLimit == -1

With no pinned pool this produces 0; with a pinned pool (e.g. 2 GiB) it produces ~0.9 * pinnedSize, sizing the limit off the pinned pool only and ignoring all non-pinned memory.

The fix extracts the hardware-derived off-heap limit computation from getPinnedPoolAndOffHeapLimits
into a shared computeEffectiveOffHeapLimit method, and uses it in computeMtReadLimit when
nonPinnedLimit == -1 to derive a concrete total from hardware instead.

Note: spark.rapids.sql.multiThreadedRead.memoryLimit.enabled defaults to false, so impact is
limited to users who have explicitly enabled the feature. The hardware-derived calculation has a
known approximation limitation in certain environments (see #13628), called out in a new code
comment.

Before (2 GiB pinned pool, off-heap limit disabled): MT read limit ≈ 1.80 GiB (90% of pinned only)

After: MT read limit ≈ 78 GiB (90% of hardware-derived off-heap)

Checklists

  • This PR has added documentation for new or modified features or behaviors.
  • This PR has added new tests or modified existing tests to cover new code paths.
    GpuDeviceManagerSuite — "MT read limit should be 90% of total off heap when off heap limit
    disabled": calls computeMtReadLimit with nonPinnedLimit=-1 and asserts the result equals
    90% of the hardware-derived off-heap total. Fails against pre-fix code, passes after.
  • Performance testing has been performed and its results are added in the PR description. Or, an issue has been filed with a link in the PR description.

Signed-off-by: Zach Puller <zpuller@nvidia.com>
@zpuller zpuller changed the title [DRAFT] base mt read limits off effective off heap limits Fix MT read memory limit defaulting to wrong size when off-heap limit is disabled Apr 1, 2026
@zpuller
zpuller marked this pull request as ready for review April 1, 2026 00:09
@greptile-apps

greptile-apps Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where the multi-threaded read memory limit was calculated incorrectly when off-heap limit tracking is disabled (nonPinnedLimit == -1), causing the limit to collapse to near-zero (0 with no pinned pool, or ~90% of pinned size only with one). The fix extracts the hardware-derived off-heap estimation into a shared private computeEffectiveOffHeapLimit method and introduces a new computeMtReadLimit function that falls back to that hardware estimate when nonPinnedLimit == -1, with a regression test that validates the corrected behavior.

Confidence Score: 5/5

Safe to merge; the fix is minimal, well-scoped, and covered by a targeted regression test.

No P0 or P1 findings. The refactoring is clean: computeEffectiveOffHeapLimit is correctly extracted as a private method, getPinnedPoolAndOffHeapLimits delegates to it, and computeMtReadLimit correctly handles the disabled-limit edge case. The test uses try/finally to clean up TestMemoryChecker state and directly validates the before/after arithmetic.

No files require special attention.

Important Files Changed

Filename Overview
sql-plugin/src/main/scala/com/nvidia/spark/rapids/GpuDeviceManager.scala Extracts computeEffectiveOffHeapLimit into a shared private method and adds computeMtReadLimit that correctly handles nonPinnedLimit==-1 (off-heap limit disabled) by falling back to a hardware-derived estimate.
tests/src/test/scala/com/nvidia/spark/rapids/GpuDeviceManagerSuite.scala Adds a regression test for computeMtReadLimit with nonPinnedLimit=-1, asserting the result equals 90% of the hardware-derived off-heap total, with proper TestMemoryChecker cleanup in finally.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[initializePinnedPoolAndOffHeapLimits] --> B[getPinnedPoolAndOffHeapLimits]
    B --> |confLimitEnabled=true| C[computeEffectiveOffHeapLimit]
    C --> D{confLimit defined?}
    D --> |yes| E[return confLimit]
    D --> |no| F[derive from hardware memory]
    B --> |confLimitEnabled=false| G[return confPinnedSize, -1]
    A --> H{multiThreadReadMemoryLimit == 0?}
    H --> |yes| I[computeMtReadLimit]
    I --> J{nonPinnedLimit >= 0?}
    J --> |yes| K[totalOffHeap = pinnedSize + nonPinnedLimit]
    J --> |no -1, FIXED| L[computeEffectiveOffHeapLimit]
    L --> M[hardware-derived estimate]
    K --> N[return 0.9 x totalOffHeap]
    M --> N
Loading

Reviews (2): Last reviewed commit: "pr comments" | Re-trigger Greptile

@zpuller

zpuller commented Apr 1, 2026

Copy link
Copy Markdown
Collaborator Author

build

1 similar comment
@zpuller

zpuller commented Apr 1, 2026

Copy link
Copy Markdown
Collaborator Author

build

@zpuller
zpuller requested a review from a team April 1, 2026 16:14
Comment thread tests/src/test/scala/com/nvidia/spark/rapids/GpuDeviceManagerSuite.scala Outdated
Comment thread sql-plugin/src/main/scala/com/nvidia/spark/rapids/GpuDeviceManager.scala Outdated
Signed-off-by: Zach Puller <zpuller@nvidia.com>
@zpuller

zpuller commented Apr 6, 2026

Copy link
Copy Markdown
Collaborator Author

build

@zpuller
zpuller requested a review from abellina April 6, 2026 21:01
@zpuller
zpuller merged commit cc2f48c into NVIDIA:main Apr 7, 2026
47 checks passed
@zpuller
zpuller deleted the mt_read_limits branch April 22, 2026 16:09
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.

[BUG] multithreaded read limit defaults to wrong size, ignores non-pinned off heap memory

3 participants