plaidml / onnx-plaidml

An ONNX backend using PlaidML
GNU Affero General Public License v3.0
28 stars 8 forks source link

About Version-5 reshape #13

Open YUIAZU000 opened 6 years ago

YUIAZU000 commented 6 years ago

I run onnx-plaidml on my model and got an error: “Version-5 reshape() is not yet implemented by the PlaidML ONNX backend” I find it caused by the function pixelshuffle I used. Do you have an incomplete implement of this operation?

earhart commented 6 years ago

In Version 1, reshape took the new shape as a list of ints. In Version 5, this was replaced with a one-dimensional input tensor. So when the model is prepared, we can't actually know the shape of anything; we find out when the model is bound to actual inputs.

I've thought a little about how to implement this: since a PlaidML function operates over symbolic-sized tensors anyway (output shapes aren't known until all input shapes have been bound), it might be possible to simply defer reshape computations. Doing this will be tricky; the program compilation cache is currently keyed off tensor sizes, not tensor contents. I think it's doable, but it'll take some time, and it'll have to be scheduled relative to other features we'd like to add.

In the meantime, if anyone feels like working on this, I'd be very happy to review PRs. :-)

YUIAZU000 commented 6 years ago

@earhart I have solved the problem. `import numpy as np import plaidml import plaidml.tile

_ctx = plaidml.Context() _device = plaidml.Device(_ctx, None)

def get_value(x): func = plaidml.tile.compose(_ctx, _device, [], [('out', x)]) invoker = plaidml.Invoker(_ctx, func) shape = invoker.get_output_shape('out') tensor = plaidml.Tensor(_device, shape) invoker.set_output('out', tensor) invoker.invoke() array = np.ndarray(x.shape.dims, dtype=plaidml.tile.PLAIDML_DTYPE_TO_NUMPY[x.shape.dtype]) with tensor.mmap_current() as view: view.copy_to_ndarray(array) return array`

You can use get_value to get the value of shape, and it works on my model.

jack-willturner commented 6 years ago

Can you give an example of how to use this?

earhart commented 6 years ago

The only problem with this approach is that we still don't have the input tensor data to use for computing the reshape() until after the inputs are bound, after the tensor's been prepared (i.e. compiled).

One other idea might be to defer the compilation: if we figure out that there's an operation whose Tile code depends on a tensor input, we could hold off on doing all the binding until we know the value of that input, and use caching to keep performance reasonable. I think we'd also want to add a check to see which tensors are actually used by the resulting program; if a tensor's only being provided to determine a shape, there's no reason to be transferring its data to the GPU.