Skip to content

Conversation

@Andy-Jost
Copy link
Contributor

Summary

Complete hashability support for core API classes by adding __eq__ and __hash__ to Buffer, LaunchConfig, Kernel, and ObjectCode.

Changes

  • Add __eq__ and __hash__ to Buffer, LaunchConfig, Kernel, ObjectCode
  • Remove type(self) from __hash__ in Event, Context (and the new classes) - CUDA handles are already unique, and this maintains the hash/equality contract for subclasses
  • Add _LAUNCH_CONFIG_ATTRS tuple for forward-compatible identity in LaunchConfig
  • Update __repr__ in LaunchConfig to use the same attribute list
  • Add parameterized hash tests for all 8 core API classes

Identity basis:

Class Identity
Buffer (ptr, size)
LaunchConfig (grid, cluster, block, shmem_size, cooperative_launch)
Kernel handle
ObjectCode handle (triggers lazy load)

Stream, Event, Context, Device already had __eq__/__hash__.

Test Plan

  • New parameterized tests in test_hashable.py cover all 8 core classes
  • All existing hash/equality tests pass
  • Full test suite passes locally (1599 tests)

Make these classes hashable and comparable:
- Buffer: identity based on (type, ptr, size)
- LaunchConfig: uses _LAUNCH_CONFIG_ATTRS tuple for forward-compatible
  identity; also updates __repr__ to use the same attribute list
- Kernel: identity based on (type, handle)
- ObjectCode: identity based on (type, handle), triggers lazy load

Stream, Event, Context, Device already had __eq__/__hash__.
Make these classes hashable and comparable:
- Buffer: identity based on (ptr, size)
- LaunchConfig: uses _LAUNCH_CONFIG_ATTRS tuple for forward-compatible
  identity; also updates __repr__ to use the same attribute list
- Kernel: identity based on handle
- ObjectCode: identity based on handle, triggers lazy load

Remove type(self) from __hash__ in Event, Context, Buffer, LaunchConfig,
Kernel, ObjectCode - CUDA handles are already unique, and removing
type(self) maintains the hash/equality contract for subclasses.

Add parameterized hash tests for all 8 core API classes.

Stream, Device already had correct __eq__/__hash__ without type(self).
@Andy-Jost Andy-Jost added this to the cuda.core beta 12 milestone Jan 25, 2026
@Andy-Jost Andy-Jost added enhancement Any code-related improvements P1 Medium priority - Should do cuda.core Everything related to the cuda.core module labels Jan 25, 2026
@Andy-Jost Andy-Jost self-assigned this Jan 25, 2026
@copy-pr-bot
Copy link
Contributor

copy-pr-bot bot commented Jan 25, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@Andy-Jost
Copy link
Contributor Author

/ok to test e182f4c

Comment on lines +25 to +41
def sample_device(init_cuda):
return Device()


@pytest.fixture
def sample_stream(sample_device):
return sample_device.create_stream()


@pytest.fixture
def sample_event(sample_device):
return sample_device.create_event()


@pytest.fixture
def sample_context(sample_device):
return sample_device.context
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Once this change and the change adding __weakref__ members are both merged, I plan to revisit these fixtures (which overlap with test_weakref.py). There is an opportunity to rewrite and simplify test_hashable.py, test_comparable.py and test_weakref.py, possibly combining them.

@github-actions

This comment has been minimized.

@Andy-Jost
Copy link
Contributor Author

/ok to test a208225

@Andy-Jost
Copy link
Contributor Author

/ok to test e819a5a

@kkraus14
Copy link
Collaborator

this maintains the hash/equality contract for subclasses

I think the reason to include type was to make it so subclasses don't hash / compare equally. That being said, I don't think there was a strong reason for that behavior and a subclass can always override the __hash__ and __eq__ methods if they wish to have that behavior.

Comment on lines +137 to +138
def _identity(self):
return tuple(getattr(self, attr) for attr in _LAUNCH_CONFIG_ATTRS)
Copy link
Collaborator

Choose a reason for hiding this comment

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

It may be worth caching this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is LaunchConfig intended to be immutable? Currently it is not:

>>> config = LaunchConfig(grid=(1,2),  block=1)
>>> config
LaunchConfig(grid=(1, 2, 1), cluster=None, block=(1, 1, 1), shmem_size=0, cooperative_launch=False)
>>> config.grid = (2,2,2)
>>> config
LaunchConfig(grid=(2, 2, 2), cluster=None, block=(1, 1, 1), shmem_size=0, cooperative_launch=False)

Copy link
Collaborator

Choose a reason for hiding this comment

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

In theory we could invalidate the cache on setter functions, but we can punt this to if it ever becomes a bottleneck.

Change object_code fixture to compile to cubin instead of ptx to avoid
CUDA_ERROR_UNSUPPORTED_PTX_VERSION when the toolkit version is newer
than the driver version on test machines.

Also remove outdated "type salt" reference from assertion message.
@Andy-Jost
Copy link
Contributor Author

/ok to test 09b11e6

@Andy-Jost
Copy link
Contributor Author

this maintains the hash/equality contract for subclasses

I think the reason to include type was to make it so subclasses don't hash / compare equally. That being said, I don't think there was a strong reason for that behavior and a subclass can always override the __hash__ and __eq__ methods if they wish to have that behavior.

I thought so as well, but then I found tests explicitly checking that subclasses compare equal to non-subclasses managing the same driver resource. This also came up in a recent issue where it was decided for streams to use CUstream (only) as the basis of identity.

@Andy-Jost Andy-Jost merged commit c5d1417 into NVIDIA:main Jan 28, 2026
247 of 252 checks passed
@Andy-Jost Andy-Jost deleted the add-hashable branch January 28, 2026 14:52
@github-actions
Copy link

Doc Preview CI
Preview removed because the pull request was closed or merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuda.core Everything related to the cuda.core module enhancement Any code-related improvements P1 Medium priority - Should do

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants