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

[Feat][Experimental] Support parallel computing (embarassingly parallel) #3685

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from

Conversation

Bobholamovic
Copy link
Member

@Bobholamovic Bobholamovic commented Mar 20, 2025

本PR主要为PaddleX增加一个实验性质的并行加速功能,旨在优化代码库中广泛存在的类似:[func(item) for item in data]这样的过易并行的逻辑。

PR内容

  1. 新增基于joblib的并行加速功能。
    • 新增maybe_parallelize函数,可用于标记代码库中的过易并行逻辑,并在配置满足要求时将其并行化。
    • 支持设置一个全局执行器以复用线程池/进程池,提升效率;也支持通过joblib.parallel_config从库的外部定制PaddleX的默认并行计算行为。
    • 通过环境变量控制该功能是否开启,默认关闭。
  2. 基于新增的并行加速功能,优化了数据读取操作、大部分模块的前后处理操作以及部分产线的操作。目前的实现,在我的机器上,batch size为32时,启动并行计算功能后,默认配置可以将PP-DocLayout-L的端到端推理时间缩短一半,将PP-OCRv4_mobile_det的预处理时间缩短为原本的1/10
  3. 定位到目前OCR类产线推理的一大性能瓶颈在于scipy.ndimage.rotate的速度太慢了。使用OpenCV编写了替代的高效实现,初步测量对1024*2048的大图加速可以达到近百倍,但与原实现不是完全对齐(看起来可能主要是输出尺寸和align-corner方面有差别),需确认这个替代实现是否可接受。在我的机器上实验,使用新的实现,可以让OCR产线处理一个6页示例PDF的时间从13s降低到6s。 => 2025.3.26,替代实现的精度被相关同学评估为可以接受,为了让这个PR的内容更专一,这一点涉及的修改被移动到更相关的 opt processors #3714

缺陷与待办

  1. 新增的并行加速功能对OCR类产线的优化不明显,这主要是因为当前OCR类产线的许多模块接受的batch size都是1。
  2. 需要对改造的前后处理等操作进行正确性验证和benchmark,评估是否适合并行化。目前只对OCR类模块做了评估。

Copy link

paddle-bot bot commented Mar 20, 2025

Thanks for your contribution!

@Bobholamovic Bobholamovic removed the wip label Mar 21, 2025
@TingquanGao
Copy link
Collaborator

对于并行这个问题。我最近在考虑是否有必要,在基类支持非generator行为的predict方法(假定为get_prediction()),即对于输入数据一次性处理并返回结果,和这个PR类似都是解决该问题。
结合这个PR的思路,我觉得或许可以在基类定义get_prediction(),其实现同样沿用这个PR的实现逻辑,这样的好处是,相比maybe_parallel,get_prediction更加直观,对用户可能更友好。
Bobholamovic也评估下呢。

return _executor


def maybe_parallelize(func, /, *iterables, executor=None):
Copy link
Member Author

Choose a reason for hiding this comment

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

因为根据实际配置,有可能并行处理,也有可能不并行处理,只能保证“可能被并行处理”,所以用这个名字防止误解。

if executor is None:
executor = _executor
if executor is None:
executor = joblib.Parallel(n_jobs=_get_default_num_jobs(), prefer="threads")
Copy link
Member Author

Choose a reason for hiding this comment

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

经过实际测试,如果我们主要用在底层操作,并且操作中多涉及numpy数组的计算(numpy中许多函数是release GIL的),默认使用多线程比多进程性能更高,数据搬移的开销可能导致多进程比单线程串行处理还慢。

@@ -57,7 +57,8 @@ def resize_norm_img(self, img, max_wh_ratio):
resized_w = int(math.ceil(imgH * ratio))
resized_image = cv2.resize(img, (resized_w, imgH))
resized_image = resized_image.astype("float32")
resized_image = resized_image.transpose((2, 0, 1)) / 255
resized_image = resized_image.transpose((2, 0, 1))
resized_image /= 255
resized_image -= 0.5
resized_image /= 0.5
padding_im = np.zeros((imgC, imgH, imgW), dtype=np.float32)
Copy link
Member Author

Choose a reason for hiding this comment

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

没有对OCRReisizeNormImg进行并行化,是因为实测发现这样效率更低。

@Bobholamovic
Copy link
Member Author

对于并行这个问题。我最近在考虑是否有必要,在基类支持非generator行为的predict方法(假定为get_prediction()),即对于输入数据一次性处理并返回结果,和这个PR类似都是解决该问题。 结合这个PR的思路,我觉得或许可以在基类定义get_prediction(),其实现同样沿用这个PR的实现逻辑,这样的好处是,相比maybe_parallel,get_prediction更加直观,对用户可能更友好。 Bobholamovic也评估下呢。

maybe_parallel主要是作为内部API,初衷是用来标记可以执行优化的逻辑,专注于固定的pattern,试图相对降低开发者(与用户相对)编写并行代码的难度。实际上目前这个方案的一个很大的问题是允许在什么粒度施加maybe_parallel——要是之后代码变得复杂,无意中出现了嵌套parallel的情况,就有可能会出现死锁等意料外的问题。也是出于这个原因,现在我选择只在一些相对“标准化”的位置(比如按照开发文档,每个模块都有标准化的布局)添加,其他的多数位置有些太“自由”了,可能只能逐个文件来分析。不过,如果我们进一步扩大“标准化”的范围,比如基类能有get_prediction这样的契约,我想应该对降低开发成本、减小出错概率有很大帮助,直观的好处就是我们可以在一个统一的粒度做统一的控制。目前唯一可能担心的点是如果这个固定的粒度比较粗,有可能加速效果不如细粒度的优化。当然,这些都需要测试后才知道,整体上我支持这个想法~

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.

2 participants