Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Could not serialize dali.fn.python_function #5059

Open
1 task done
omair18 opened this issue Sep 25, 2023 · 6 comments
Open
1 task done

Could not serialize dali.fn.python_function #5059

omair18 opened this issue Sep 25, 2023 · 6 comments
Assignees
Labels
question Further information is requested

Comments

@omair18
Copy link

omair18 commented Sep 25, 2023

Describe the question.

I am trying to serialize a pipeline which uses dali.fn.python_function but I'm getting the following error.

RuntimeError: [/opt/dali/dali/pipeline/pipeline.cc:776] Assert on "spec.GetSchema().IsSerializable()" failed: Could not serialize the operator: DLTensorPythonFunctionImpl 

Here's my pipeline

def rectangular_pad(image, canvas, pad_x, pad_y):
        h, w, c = image.shape
        paste_x = int(pad_x/2)
        paste_y = int(pad_y/2)
        canvas[paste_y: paste_y + h, 
            paste_x: paste_x + w] = image
        return canvas
@dali.pipeline_def(batch_size=256, num_threads=4, device_id=0, exec_async=False, exec_pipelined=False)
def pipe():
    images = dali.fn.external_source(device="cpu", name="DALI_INPUT_0")
    images = dali.fn.decoders.image(images, device="cpu", output_type=types.BGR)
    orig_shape = dali.fn.shapes(images)
    orig_width = orig_shape[1]
    orig_height = orig_shape[0]

    scale_x = target_width / orig_width
    scale_y = target_height / orig_height
    scale_min = dali.math.min(left=scale_x, right=scale_y)

    new_width = orig_width * scale_min
    new_height = orig_height * scale_min

    pad_x = target_width - new_width
    pad_y = target_height - new_height
    resized_images = dali.fn.resize(images, resize_x=new_width, resize_y=new_height, 
                            dtype=types.FLOAT, interp_type=types.INTERP_LINEAR, antialias=False)
    canvas = dali.fn.constant(idata=128, shape=[target_height, target_width, 3])
    out_images = dali.fn.python_function(images, canvas, pad_x, pad_y, function=rectangular_pad, num_outputs=1, batch_processing=False)
        
    return out_images, images

Check for duplicates

  • I have searched the open bugs/issues and have found no duplicates for this bug report
@omair18 omair18 added the question Further information is requested label Sep 25, 2023
@JanuszL
Copy link
Contributor

JanuszL commented Sep 25, 2023

Hi @omair18,

Thank you for reaching out. I'm sorry but by design python operator cannot be serialized as we cannot save the Python code and for now together with the test of the DALI pipeline representation. What you can do is use crop or slice operators with out_of_bounds_policy set.

@omair18
Copy link
Author

omair18 commented Sep 25, 2023

Hi @JanuszL ,

Thank you for your quick response.
Can you guide me how to implement rectangular padding on images using dali.fn like I did using python_function ?

@omair18
Copy link
Author

omair18 commented Sep 25, 2023

Hi @JanuszL .
I have implemented rectangular padding via dali.fn.crop but if I try to use device="mixed" in dali.fn.decoders I'm getting

Named arguments inputs to operators must be CPU data nodes. However, a GPU data node was provided (op: 'Resize', input: '__ArithmeticGenericOp_9')

Can you please help?

@JanuszL
Copy link
Contributor

JanuszL commented Sep 25, 2023

Hi,

This is one of the DALI limitations, that data once lands on the GPU cannot be moved back. In this case please use peek image shape operator to obtain the image shape before the decoding:

@dali.pipeline_def(batch_size=256, num_threads=4, device_id=0, exec_async=False, exec_pipelined=False)
def pipe():
    images = dali.fn.external_source(device="cpu", name="DALI_INPUT_0")
    orig_shape = dali.fn.peek_image_shape(images)
    images = dali.fn.decoders.image(images, device="cpu", output_type=types.BGR)
    orig_width = orig_shape[1]
    orig_height = orig_shape[0]

@Vincouux
Copy link

This doesn't really answer the original question which was that python function cannot be serialized. DALI support torch_python_function which is great, but cannot be serialized... Any help is welcome !

@JanuszL
Copy link
Contributor

JanuszL commented Aug 5, 2024

Hi @Vincouux,

This doesn't really answer the original question which was that python function cannot be serialized.

As I mentioned by design Python operator cannot be serialized as we cannot save the Python code and I proposed a way to express the needed operations using the native DALI operators. The serialization of the Python code imposes multiple challenges and limitations we haven't figured out how to overcome yet.
For now please try to express your flow using the DALI native operators.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants