Skip to content

Fix resource misclassification for unsorted _read_only_resource_inputs - #110665

Merged
copybara-service[bot] merged 2 commits into
tensorflow:masterfrom
apoorvdarshan:fix/auto-control-deps-unsorted-indices
Jun 29, 2026
Merged

Fix resource misclassification for unsorted _read_only_resource_inputs#110665
copybara-service[bot] merged 2 commits into
tensorflow:masterfrom
apoorvdarshan:fix/auto-control-deps-unsorted-indices

Conversation

@apoorvdarshan

Copy link
Copy Markdown
Contributor

Summary

  • Fixes a logical flaw in auto_control_deps_utils.py where _get_read_only_resource_input_indices_op and get_read_write_resource_inputs used a pointer-based linear scan that assumed _read_only_resource_inputs was always sorted.
  • When the attribute list was unsorted (e.g., [2, 0]), read-only resources were misclassified as read-write, injecting spurious control dependencies and serializing operations that should run in parallel.
  • Replaced the pointer-based scan with a set-based lookup, which is both correct for any ordering and more efficient (O(1) per lookup).

Fixes #110516

Test plan

  • Verified with the reproduction script from the issue — unsorted indices [2, 0] now correctly detect both indices [0, 2]
  • Verified sorted indices still work correctly
  • Verified empty indices edge case
  • Verified mixed resource/non-resource inputs with unsorted indices
  • Verified get_read_write_resource_inputs correctly classifies reads vs writes for unsorted indices

Replace pointer-based linear scan with set-based lookup in
_get_read_only_resource_input_indices_op and get_read_write_resource_inputs.
The previous implementation assumed the _read_only_resource_inputs attribute
was always sorted, causing read-only resources to be misclassified as
read-write when indices were unsorted, injecting spurious control dependencies.

Fixes tensorflow#110516
@google-ml-butler google-ml-butler Bot added the size:S CL Change Size: Small label Feb 18, 2026
@google-ml-butler google-ml-butler Bot added the awaiting review Pull request awaiting review label Feb 19, 2026
@keerthanakadiri keerthanakadiri added the python Pull requests that update Python code label Feb 19, 2026
@github-project-automation github-project-automation Bot moved this to Assigned Reviewer in PR Queue Feb 19, 2026
@keerthanakadiri keerthanakadiri added the prtype:bugfix PR to fix a bug label Feb 19, 2026
@google-ml-butler google-ml-butler Bot added kokoro:force-run Tests on submitted change ready to pull PR ready for merge process labels Feb 19, 2026
@kokoro-team kokoro-team removed the kokoro:force-run Tests on submitted change label Feb 19, 2026
@keerthanakadiri keerthanakadiri removed the awaiting review Pull request awaiting review label Mar 30, 2026
@nithyak0204 nithyak0204 removed the ready to pull PR ready for merge process label Jun 26, 2026
@nithyak0204
nithyak0204 requested a review from a team June 26, 2026 09:43
@google-ml-butler google-ml-butler Bot added the awaiting review Pull request awaiting review label Jun 26, 2026

@dmiltr3 dmiltr3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the contribution! The logic fix looks correct and will resolve issues with unsorted read-only resource indices.

Could you please add a unit test in tensorflow/python/framework/auto_control_deps_test.py to prevent regressions for this edge case? You can use the test snippet below, which verifies the classification behavior for unsorted, sorted, empty, and mixed index configurations:

  def testReadOnlyResourceInputsUnsorted(self):
    from tensorflow.python.framework import auto_control_deps_utils as acd_utils
    from unittest import mock

    # 1. Unsorted inputs
    input0 = mock.MagicMock()
    input0.dtype = dtypes.resource
    input1 = mock.MagicMock()
    input1.dtype = dtypes.int32
    input2 = mock.MagicMock()
    input2.dtype = dtypes.resource

    op = mock.MagicMock()
    op.type = "SomeOp"
    op.inputs = [input0, input1, input2]
    
    op.get_attr.side_effect = lambda name: [2, 0] if name == acd_utils.READ_ONLY_RESOURCE_INPUTS_ATTR else ValueError()

    # _get_read_only_resource_input_indices_op should return both indices, sorted
    self.assertEqual(
        acd_utils._get_read_only_resource_input_indices_op(op), [0, 2]
    )

    # get_read_write_resource_inputs should categorize both as reads and zero as writes
    reads, writes = acd_utils.get_read_write_resource_inputs(op)
    self.assertIn(input0, reads)
    self.assertIn(input2, reads)
    self.assertEqual(len(writes), 0)

    # 2. Empty indices
    op2 = mock.MagicMock()
    op2.type = "SomeOp"
    op2.inputs = [input0, input1, input2]
    op2.get_attr.side_effect = lambda name: [] if name == acd_utils.READ_ONLY_RESOURCE_INPUTS_ATTR else ValueError()

    self.assertEqual(
        acd_utils._get_read_only_resource_input_indices_op(op2), []
    )
    reads2, writes2 = acd_utils.get_read_write_resource_inputs(op2)
    self.assertEqual(len(reads2), 0)
    self.assertIn(input0, writes2)
    self.assertIn(input2, writes2)

    # 3. Mixed reads and writes (index 0 is read, index 2 is write)
    op3 = mock.MagicMock()
    op3.type = "SomeOp"
    op3.inputs = [input0, input1, input2]
    op3.get_attr.side_effect = lambda name: [0] if name == acd_utils.READ_ONLY_RESOURCE_INPUTS_ATTR else ValueError()

    self.assertEqual(
        acd_utils._get_read_only_resource_input_indices_op(op3), [0]
    )
    reads3, writes3 = acd_utils.get_read_write_resource_inputs(op3)
    self.assertIn(input0, reads3)
    self.assertNotIn(input2, reads3)
    self.assertIn(input2, writes3)
    self.assertNotIn(input0, writes3)

@github-project-automation github-project-automation Bot moved this from Assigned Reviewer to Reviewer Requested Changes in PR Queue Jun 26, 2026
Covers unsorted, empty, and mixed read/write resource index configurations for _get_read_only_resource_input_indices_op and get_read_write_resource_inputs, per review feedback.
@apoorvdarshan

Copy link
Copy Markdown
Contributor Author

@dmiltr3 thanks for the contribution and the detailed test snippet! Added it as testReadOnlyResourceInputsUnsorted in tensorflow/python/framework/auto_control_deps_test.py (c031f78), covering the unsorted, empty, and mixed read/write index configurations for both _get_read_only_resource_input_indices_op and get_read_write_resource_inputs.

Two small adjustments to fit the file's style, with identical coverage/behavior to your snippet:

  • Wrapped the lines to ≤80 columns (the file currently has no lines over 80).
  • Factored the mocked get_attr into a small get_attr_returning helper that raises ValueError for unset attrs, matching real Operation.get_attr semantics (which the util's except ValueError branch relies on).

PTAL 🙏

@dmiltr3
dmiltr3 self-requested a review June 27, 2026 02:33
@google-ml-butler google-ml-butler Bot added kokoro:force-run Tests on submitted change ready to pull PR ready for merge process labels Jun 27, 2026
@github-project-automation github-project-automation Bot moved this from Reviewer Requested Changes to Approved by Reviewer in PR Queue Jun 27, 2026
@kokoro-team kokoro-team removed the kokoro:force-run Tests on submitted change label Jun 27, 2026
@nithyak0204 nithyak0204 removed the awaiting review Pull request awaiting review label Jun 29, 2026
@copybara-service
copybara-service Bot merged commit 09d11d1 into tensorflow:master Jun 29, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prtype:bugfix PR to fix a bug python Pull requests that update Python code ready to pull PR ready for merge process size:S CL Change Size: Small

Projects

Status: Merged

Development

Successfully merging this pull request may close these issues.

[Bug] Logical flaw in auto_control_deps_utils.py: Resource categorization fails for unsorted _read_only_resource_inputs

7 participants