🐼提升速度
2021-10-15
| 2023-8-6
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property

目标函数加速

为了提升速度,scikit-opt 支持3种提升速度的方案:矢量化并行化缓存化
  • 矢量化:要求目标函数本身支持矢量化运算(详见代码)。矢量化运算拥有极高的性能,通常比并行化运算要快。算法中,每代对应1次矢量化运算
  • 多线程:对目标函数没什么要求,通常比一般运算要快。如果目标函数是 IO 密集型,能达到更优的性能
  • 多进程:对目标函数没什么要求,通常比一般运算要快。如果目标函数是 CPU 密集型,能达到更优的性能
  • 缓存化:把每次计算的输入和输出缓存下来,下次调用时,如果已经缓存中已经存在,那么直接取出结果,而不再调用。缓存化特别适用于输入值有限的情况,例如纯整数规划、迭代到后期的TSP问题等。
总的来说,性能上,矢量化 远远大于 多线程/多进程 大于 不加速,如果是输入值得可能个数有限,缓存化 远大于其他方案。
下面比较 不加速矢量化多线程多进程 的性能:
notion image
 
 
下面比较 不加速 和 缓存化 的性能:
notion image
 
 
notion image
 
 

算子优化加速

主要手段是 矢量化 和 逻辑化
对于可以矢量化的算子,scikit-opt 都尽量做了矢量化,并且默认调用矢量化的算子,且 无须用户额外操作
另外,考虑到有些算子矢量化后,代码可读性下降,因此矢量化前的算子也会保留,为用户进阶学习提供方便

0/1 基因的mutation

做一个mask,是一个与Chrom大小一致的0/1矩阵,如果值为1,那么对应位置进行变异(0变1或1变0)自然想到用整除2的方式进行
如此就实现了一次性对整个种群所有基因变异的矢量化运算。用pycharm的profile功能试了一下,效果良好
再次改进。我还嫌求余数这一步速度慢,画一个真值表
A
mask:是否变异
A变异后
1
0
1
0
0
0
1
1
0
0
1
1
发现这就是一个 异或
测试发现运行速度又快了1~3倍,与最原始的双层循环相比,快了约20倍
 
 

0/1基因的crossover

同样思路,试试crossover.
  • mask同样,1表示对应点交叉,0表示对应点不交叉
做一个真值表,总共8种可能,发现其中只有2种可能基因有变化(等位基因一样时,交叉后的结果与交叉前一样)
A基因
B基因
是否交叉
交叉后的A基因
交叉后的B基因
1
0
1
0
1
0
1
1
1
0
可以用 异或 和  来表示是否变化的表达式: mask = (A^B)&C,然后可以计算了A^=mask, B^=mask
测试结果,效率提升约1倍
 
 

锦标赛选择算子selection_tournament

实战发现,selection_tournament 往往是最耗时的,几乎占用一半时间,因此需要优化。
优化前的算法是遍历,每次选择一组进行锦标赛。但可以在二维array上一次性操作。
发现own time 和time 都降为原来的10%~15%,效率提升了约9倍
  • Scikit-opt
  • 人工鱼群算法AFSA层次分析法 AHP
    目录