大家好,这两天遇到一个运算速度的问题,就是我的程序是关于图像处理的,有的函数是要通过把一张图片的每个像素点扫描,然后计算一些值,比如这样一个场景:有一张画布,上面有 3 个元素,我现在要计算每个空白位置的像素点与这三个元素之间的最短距离,这样如果画布面积太大,就会导致算法运行时间过长,实测的话 800x600 的画布,将这个函数循环迭代 600 次,就得耗时 10 个小时+,所以我想通过并行计算来试试,因为目前的服务器配置是 8 核 E5 2650V3 的,感觉自己的程序只用到了一个核。但是关于这方面的知识我不是很懂,所以请教一下各位,谢谢!
还是V站的前辈见识比较广,我要查一下这些技术,消化一下。。。。谢谢各位
1
xujunfu 2016-11-25 20:47:45 +08:00 via iPhone
cuda mpi openmp
|
2
justou 2016-11-25 21:00:32 +08:00
这种问题用 GPU 算比 CPU 并行高效得多
比如 opengl 还有 1L 提到的 cuda, 都有 python 接口 |
3
zhuangzhuang1988 2016-11-25 21:17:42 +08:00
奇怪! 为何要循环做, 计算这个问题应该有数学方法直接解决的。。
|
4
sagaxu 2016-11-25 21:23:05 +08:00 via Android
自己搜索 python gil
|
5
fffflyfish OP @justou 用的是阿里云服务器,貌似没看见有 GPU ,我想的是把一张图片切割然后分配到各个线程里去计算, cuda 的话感觉只是对矩阵运算的时候优势会大一点
|
6
fffflyfish OP @zhuangzhuang1988 我这个问题就是来自一篇论文的函数,按照文章的说法,就是逐个像素的计算,我想的优化方法就是类似卷积神经网络里的汇聚层一样,但是现在是想先利用下当前服务器 8 核这个优势
|
7
fffflyfish OP @sagaxu 看起来不错,谢谢
|
8
justou 2016-11-25 21:40:03 +08:00
哦, 我以为就用自己 PC 算...
上面打错了, 想写 opencl, 虽然 opengl 的计算着色器也能完成 图片就是一个矩阵, 放到显卡上, 每个计算单元计算一个像素跟三个元素的距离, 最后得到最短距离跟对应像素, 不需要任何循环 |
9
zhuangzhuang1988 2016-11-25 21:49:22 +08:00
如果没有 gpu
用 tbb 吧。。 这货参数配置得好,能让你的服务器爽死。。 |
10
fffflyfish OP |
11
stamaimer 2016-11-25 23:47:01 +08:00 via iPhone
我感觉你这个问题,写个多进程程序就能解决。
|
12
lll9p 2016-11-26 00:08:59 +08:00 via Android
想办法向量化啊, py 的循环多慢啊。。
|
13
tigerstudent 2016-11-26 00:12:54 +08:00
如果只是简单地改成多进程,也不过是将 10 小时缩短到一两个小时吧,效果并不太大。
|
14
henices 2016-11-26 11:45:21 +08:00 via Android
pool.map
|
15
stamaimer 2016-11-26 12:01:10 +08:00 via iPhone
@tigerstudent 你测试过了?
|
16
fffflyfish OP |
17
Jblue 2016-11-26 20:16:54 +08:00
将三个图片等分,然后并行跑如何呢, pillow 优于 pil 。
|
18
fffflyfish OP @Jblue 哈我用的就是 pillow ,这个方法我也想过,但是因为要求元素之间最短距离,分开的话就不知道怎么处理了,毕竟元素的位置分散在画布上
|
19
wjidea 2016-11-27 11:19:49 +08:00
multiprocessing
|
20
congeec 2016-11-27 13:41:33 +08:00 via iPhone
@fffflyfish 你用 pillow-simd 了?
|
21
fffflyfish OP @congeec 没,就是普通的 pillow
|
22
linhua 2016-11-27 22:06:53 +08:00
|
23
fffflyfish OP @linhua 哇,简直不能更 cool ,谢谢!
|
24
congeec 2016-11-29 03:46:09 +08:00 via iPhone
@fffflyfish 如果底层还是 pillow ,用 cpu 算,还是建议试试 simd 版本
|
25
fffflyfish OP @congeec 嗯,之前查过了,这个 simd 版本对 cpu 并行有过优化,可以可以,谢谢啦
|
26
justou 2016-12-02 17:11:58 +08:00
我实际操作了下你这个问题, 把问题简化成了: 计算图片上到若干像素距离最短的位置, 效率并不算太差啊
到 3, 10, 30, 81 个像素最短距离的计算时间分别是: 160 ms, 460 ms, 1.34 s, 3.55 s, 时间线性递增, 还没用 opencl 试 (注: 当点数过多的时候最短距离的位置不一定只有一个) https://gist.github.com/justou/b64a0b73fe198a2b6cdb1c72b3459ad8 |
27
fffflyfish OP @justou 好优雅的代码!不过你现在把画布上的一个元素简化成了一个像素点(就是你代码里随机产生的位置),但是对于我现在做的东西来说,这个元素是不能简单的以一个像素点来看待,必须是一个 bounding box , 比如说一张广告,上面的标题元素,比如字号为 60 ,那么它占的像素面积就是一个 axb 大小的矩形框,如果求图片空白区域的每个像素点(无元素的地方)到它的距离,这就有点麻烦了,因为这个元素也是有很多像素点的, 我现在用的方法是 python 里的 scipy 的 distance_transform_edt 函数,链接: https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.morphology.distance_transform_edt.html
这是目前我找到的最好的解决方法,但是计算时间还是不理想,这两天在看 multiprocess 的东西,应该会有用。 非常感谢您能腾出时间来考虑我的问题,谢谢! |