serge-sans-paille / pythran

Ahead of Time compiler for numeric kernels
https://pythran.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.99k stars 190 forks source link

AssertionError when trying to set an array shape/strides #2224

Open ogauthe opened 1 month ago

ogauthe commented 1 month ago

Hi!

When trying to manually set an array shape, pythran triggers an AssertionError.

# pythran export set_shape(float64[:, :] order(C), (int64, int64, int64))
def set_shape(arr, sh):
    arr.shape = sh
    return arr
Traceback (most recent call last):
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/bin/pythran", line 8, in <module>
    sys.exit(run())
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/run.py", line 181, in run
    pythran.compile_pythranfile(args.input_file,
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/toolchain.py", line 501, in compile_pythranfile
    output_file = compile_pythrancode(module_name, fd.read(),
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/toolchain.py", line 402, in compile_pythrancode
    module, error_checker = generate_cxx(module_name, pythrancode, specs, opts,
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/toolchain.py", line 146, in generate_cxx
    pm, ir, docstrings = front_middle_end(module_name, code, optimizations,
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/toolchain.py", line 113, in front_middle_end
    refine(pm, ir, optimizations, report_times)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/middlend.py", line 31, in refine
    pm.apply(NormalizeMethodCalls, node, run_times)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/passmanager.py", line 243, in apply
    ret=a.apply(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/passmanager.py", line 200, in apply
    new_node = self.run(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/passmanager.py", line 189, in run
    n = super(Transformation, self).run(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/passmanager.py", line 97, in run
    return self.visit(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/passmanager.py", line 79, in visit
    return super(ContextManager, self).visit(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/ast.py", line 418, in visit
    return visitor(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/transformations/normalize_method_calls.py", line 50, in visit_Module
    self.generic_visit(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/ast.py", line 494, in generic_visit
    value = self.visit(value)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/passmanager.py", line 79, in visit
    return super(ContextManager, self).visit(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/ast.py", line 418, in visit
    return visitor(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/transformations/normalize_method_calls.py", line 65, in visit_FunctionDef
    self.generic_visit(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/ast.py", line 494, in generic_visit
    value = self.visit(value)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/passmanager.py", line 79, in visit
    return super(ContextManager, self).visit(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/ast.py", line 418, in visit
    return visitor(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/transformations/normalize_method_calls.py", line 85, in visit_Assign
    n = self.generic_visit(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/ast.py", line 494, in generic_visit
    value = self.visit(value)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/passmanager.py", line 79, in visit
    return super(ContextManager, self).visit(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/ast.py", line 418, in visit
    return visitor(node)
  File "/mnt/sw/nix/store/71ksmx7k6xy3v9ksfkv5mp5kxxp64pd6-python-3.10.13-view/lib/python3.10/site-packages/pythran/transformations/normalize_method_calls.py", line 201, in visit_Attribute
    assert node.attr in ('real', 'imag'), "only store to imag/real"
AssertionError: only store to imag/real

If I understand correctly the code of visit_Attribute, pythran fails to detect I want a setattr and not a getattr. This may be unsupported, but then the error message should mention it. The same errors arises when trying to set strides instead of shape.

Context: I want to implement

def slice_reshape_transpose(old_mat, r1, r2, c1, c2, old_tensor_shape, perm):
    return old_mat[r1:r2, c1:c2].reshape(old_tensor_shape).transpose(perm)

However currently pythran copies the data, which I want to avoid. I am trying to use a lower level approach and to replicate np.lib.stride_tricks.as_strided by manually setting shape and strides.

serge-sans-paille commented 1 month ago

I can only confirm that it's not officially supported. But it looks like something worth investigating for shapes... but for strides I don't think this will. I'll first give a try to supporting your original attempt.