This repository was archived by the owner on Jun 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 237
This repository was archived by the owner on Jun 10, 2024. It is now read-only.
how to avoid race condition when using PySurfaceConverter in multiple processes? #554
Copy link
Copy link
Open
Description
Race conditions occur when using PySurfaceConverter in multiple processes. #506 suggests cloning the output surface, which reduces the problem a lot but does not solve it.
As the following code shows, we convert the same surface twice, but the results are not equal when using multiple processing.
#! /usr/bin/env python
# coding: utf-8
# pylint: disable=all
import multiprocessing
import numpy as np
import PyNvCodec as nvc
import PytorchNvCodec as pnvc
class NvColorConverter:
"Color converter using PySurfaceConverter."
def __init__(self, width, height, gpuid=0):
# yapf: disable
self.width, self.height = width, height
self.context = nvc.ColorspaceConversionContext(
nvc.ColorSpace.BT_601, nvc.ColorRange.MPEG)
self.to_yuv = nvc.PySurfaceConverter(
width, height, nvc.PixelFormat.NV12,
nvc.PixelFormat.YUV420, gpuid)
self.to_rgb = nvc.PySurfaceConverter(
width, height, nvc.PixelFormat.YUV420,
nvc.PixelFormat.RGB, gpuid)
self.to_planar = nvc.PySurfaceConverter(
width, height, nvc.PixelFormat.RGB,
nvc.PixelFormat.RGB_PLANAR, gpuid)
self.downloader = nvc.PySurfaceDownloader(
width, height, nvc.PixelFormat.RGB_PLANAR, gpuid)
# yapf: enable
def convert_color(self, surface):
surface = self.to_yuv.Execute(surface, self.context)
surface = self.to_rgb.Execute(surface, self.context)
surface = self.to_planar.Execute(surface, self.context)
# We clone the surface as suggested.
surface = surface.Clone()
frame = np.ndarray(shape=(0, ), dtype=np.uint8)
self.downloader.DownloadSingleSurface(surface, frame)
return frame
# arg is a placeholder
def test_decode_video(arg):
path, gpuid = "./test.mp4", 0
dec = nvc.PyNvDecoder(path, gpuid)
converter = NvColorConverter(dec.Width(), dec.Height(), gpuid)
for i in range(dec.Numframes()):
surface = dec.DecodeSingleSurface()
if surface.Empty(): break
# We use the same converter to convert the same surface twice,
# When processes = 1, both arrays have the same value,
# When processes > 1, two arrays are not equal.
array1 = converter.convert_color(surface)
array2 = converter.convert_color(surface)
if not np.array_equal(array1, array2):
print("frame not match")
def main():
with multiprocessing.Pool(processes=8) as pool:
pool.map(test_decode_video, [None] * 16)
if __name__ == "__main__":
main()Metadata
Metadata
Assignees
Labels
No labels