Skip to content

Fix dpnp.einsum memory-layout - #3058

Open
abagusetty wants to merge 3 commits into
IntelPython:masterfrom
abagusetty:fix-einsum-order-k-contiguity
Open

Fix dpnp.einsum memory-layout#3058
abagusetty wants to merge 3 commits into
IntelPython:masterfrom
abagusetty:fix-einsum-order-k-contiguity

Conversation

@abagusetty

Copy link
Copy Markdown
Contributor

One more minor layout issue detected during an app-testing in comparison to numpy behavior:

Fixes: #3056

  • Have you provided a meaningful PR description?
  • Have you added a test, reproducer or referred to an issue with a reproducer?
  • Have you tested your changes locally for CPU and GPU devices?
  • Have you made sure that new changes do not introduce compiler warnings?
  • Have you checked performance impact of proposed changes?
  • Have you added documentation for your changes, if necessary?
  • Have you added your changes to the changelog?

@intel-python-devops

Copy link
Copy Markdown

Can one of the admins verify this patch?

@coveralls

coveralls commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Coverage Status

No base build to compare — abagusetty:fix-einsum-order-k-contiguity into IntelPython:master

Comment thread dpnp/tests/test_linalg.py
result = dpnp.einsum(subscripts, ia, order=order)
expected = numpy.einsum(subscripts, a, order=order)
assert result.get_array()._pointer == ia.get_array()._pointer
assert result.strides == expected.strides

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.

Might fail on non-fp64 device

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

good catch, the strides are byte strides. Pinned the operand to dtype.dpnp.default_float_type()

raise ValueError(
f"order must be one of 'C', 'F', 'A', or 'K' (got '{order}')"
)
if order == "A":

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.

Suggested change
if order == "A":
if order in ("A", "K"):

needs to fix:

import numpy as np
import dpnp

# F-contiguous @ C-contiguous, default order="K"
a = np.asarray(np.random.random((4, 5)), order="F")
b = np.asarray(np.random.random((5, 6)), order="C")

n = np.einsum("ij,jk->ik", a, b)                          # order="K" default
d = dpnp.einsum("ij,jk->ik", dpnp.asarray(a), dpnp.asarray(b))

print(n.flags.c_contiguous, n.flags.f_contiguous)   # True  False   (NumPy: C)
print(d.flags.c_contiguous, d.flags.f_contiguous)   # False True    (dpnp:  F)  -- mismatch

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

True False
True False

Comment thread dpnp/dpnp_utils/dpnp_utils_einsum.py Outdated

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.

size-0 operand path ignores out= and order= and causes:

import numpy as np
import dpnp


def show(tag, mod, asnp):
    # size-0 contracted dim `j`, non-empty (2, 4) output
    a = mod.ones((2, 0))
    b = mod.ones((0, 4))

    # 1) out= should be filled and returned
    out = mod.full((2, 4), 9.0)
    r = mod.einsum("ij,jk->ik", a, b, out=out)
    out_np = asnp(out)
    print(f"[{tag}] out=  -> r is out: {r is out!s:5}  "
          f"out all-zeros: {bool((out_np == 0).all())!s:5}  (expect: True / True)")

    # 2) explicit order='F' should give an F-contiguous result
    rf = mod.einsum("ij,jk->ik", a, b, order="F")
    print(f"[{tag}] order='F' -> f_contiguous: {rf.flags.f_contiguous!s:5} "
          f"c_contiguous: {rf.flags.c_contiguous!s:5}  (expect: True / False)")

show("numpy", np, lambda x: x)
# Out: [numpy] out=  -> r is out: True   out all-zeros: True   (expect: True / True)
# Out: [numpy] order='F' -> f_contiguous: True  c_contiguous: False  (expect: True / False)

show("dpnp ", dpnp, dpnp.asnumpy)
# Out: [dpnp ] out=  -> r is out: False  out all-zeros: False  (expect: True / True)
# Out: [dpnp ] order='F' -> f_contiguous: False c_contiguous: True   (expect: True / False)

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.

dpnp.einsumdiffers with numpy in the memory layout

4 participants