Skip to content

Comments

gh-144995: Optimize memoryview == memoryview#144996

Open
vstinner wants to merge 4 commits intopython:mainfrom
vstinner:memoryview_equal
Open

gh-144995: Optimize memoryview == memoryview#144996
vstinner wants to merge 4 commits intopython:mainfrom
vstinner:memoryview_equal

Conversation

@vstinner
Copy link
Member

@vstinner vstinner commented Feb 19, 2026

@vstinner
Copy link
Member Author

Results of the benchmark from the issue:

bytes 0.000122 seconds
mview 0.000146 seconds
⇒ 1.197965 time slower

memoryview comparison complexity is no longer O(n) but O(1): values are no longer compared.

}

static int
is_float_format(const char *format)
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this cover the complex types?

import numpy as np
a = np.array([1+2j, 3+4j, float('nan')], dtype=np.complex128)
mv = memoryview(a)
mv == mv # False

Copy link
Member Author

Choose a reason for hiding this comment

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

This memory format is Zd. Oh, my change doesn't work for this memoryview. I should replace the blocklist with an allowlist. I'm not a memoryview/buffer expert. I didn't know that 3rd party projects can have their own format.

@vstinner
Copy link
Member Author

@eendebakpt: I updated the PR to allow formats known to be safe for pointer comparison (integer types), instead of blocking formats known to use floats.

I excluded the format P since I don't know well this format. Or can we allow it?

@eendebakpt
Copy link
Contributor

@eendebakpt: I updated the PR to allow formats known to be safe for pointer comparison (integer types), instead of blocking formats known to use floats.

I excluded the format P since I don't know well this format. Or can we allow it?

I think adding the P is fine (but I am no expert either). Leaving it out is the safe option, we can reconsider if this turns out to be a performance bottleneck.

Co-authored-by: Pieter Eendebak <pieter.eendebak@gmail.com>
const char *format = vv->format;
if (format != NULL) {
// Exclude formats "d" (double), "f" (float), "e" (16-bit float)
// and "P" (void*)
Copy link
Member

Choose a reason for hiding this comment

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

Why exclude "P"?

if (format != NULL) {
// Exclude formats "d" (double), "f" (float), "e" (16-bit float)
// and "P" (void*)
can_compare_ptr = (strchr("bBchHiIlLnNqQ?", format[0]) != NULL
Copy link
Member

Choose a reason for hiding this comment

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

Note that format can starts with "@".

a = array.array(float_format, [1.0, 2.0, float('nan')])
m = memoryview(a)
# nan is not equal to nan
self.assertFalse(m == m)
Copy link
Member

Choose a reason for hiding this comment

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

Test also !=.

with self.subTest(format=int_format):
a = array.array(int_format, [1, 2, 3])
m = memoryview(a)
self.assertTrue(m == m)
Copy link
Member

Choose a reason for hiding this comment

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

Test also !=.

# A memoryview is equal to itself: there is no need to compare
# individual values. This is not true for float values since they can
# be NaN, and NaN is not equal to itself.
for int_format in 'bBhHiIlLqQ':
Copy link
Member

Choose a reason for hiding this comment

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

Can "?" be tested? Can format starting with "@" be tested? Can the null format be tested?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants