Python 性能分析

Python 性能分析,大型数据算法的核心要素之一是执行某种分治策略,这点对函数式编程和命令式编程都是成立的。

可以通过下面3种方法提高处理速度。

  • 使用并行策略实现并发计算,例如使用4核处理器,处理时间大约变为原来的1/4,上面的曼哈顿距离计算可以缩短到8分钟左右。
  • 保存中间计算结果以避免重复计算,搞清楚需要计算的相同颜色和不同颜色的数量。
  • 使用新算法。

可以将后两种方法结合,比较所有源色彩和目标色彩。与逐个像素的计算方法相比,这种方式预先穷举所有可能的映射关系来避免重复计算。本质上这是将一系列比较运算转换成了在映射对象中进行查表操作。

对一张具体的图片进行预先的、源到目标的穷举映射计算时,首先要整体评估问题规模,本教程随附的代码中包含一张名为“IMG_2705.jpg”的图片。下面的算法初步估算该图片的颜色元组的总规模:

from collections import defaultdict, Counter
palette = defaultdict(list)
for xy, rgb in pixel_iter(img):
    palette[rgb].append(xy)

w, h = img.size
print("Total pixels", w * h)
print("Total colors", len(palette))

对所有像素,按照其颜色值进行分组,将相同颜色的像素放入同一个列表中,从计算结果中可以得到如下信息:

  • 像素总数为9 980 928,对于一个10MB大小的图片来说,这个数字在意料之中;
  • 共有210 303种颜色,计算这些颜色与133种目标颜色之间的欧氏距离,只需27 970 299次计算,大约花费76秒;
  • 使用3比特遮罩0b11100000时,在总共 2^3x2^3x2^3=512 种可能的颜色集合中,实际用到214种;
  • 使用4比特遮罩0b11110000时,实际用到1150种;
  • 使用5比特遮罩0b11111000时,实际用到5845种;
  • 使用6比特遮罩0b11111100时,在总共 2^6x2^6x2^6=262144 种颜色集合中,实际用到27726种。

这有助于我们理解如何重组数据结构、快速实现颜色适配计算并重建图像,以避免进行十亿级的比较运算。

使用遮罩的作用是保留作用大的比特,去掉作用小的比特,比如有一个红色值为200的颜色,可以使用Python bin()函数查看其二进制表示。

>>> bin(200)
'0b11001000'
>>> 200 & 0b11100000
192
>>> bin(192)
'0b11000000'

表达式200 & 0b11100000擦除了颜色的最低5比特,保留了最高3比特,最终结果是大小为192的红色值。
对RGB三元组的遮罩处理如下所示:

masked_color = tuple(map(lambda x: x & 0b11100000, c))

使用 & 运算符选择特定的比特,只保留红、绿、蓝的前3比特代替之前完整的颜色值,基于它们创建Counter对象后,可知使用遮罩后共产生214个颜色值,不到理论颜色值数量的一半。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程