如何优化使用pandas生成最多6音和弦的慢迭代脚本运行速度
问题解答
总数量计算验证
你给出的总和弦数计算是正确的,这是首项12、公比12、共6项的等比数列求和,最终结果确实为3257436。
性能瓶颈分析
你当前代码运行极慢的核心原因有3个:
- 频繁使用
DataFrame.append:该操作每次都会全量拷贝现有DataFrame,数据量越大拷贝开销越高,300万次append的时间开销会指数级上升 - 嵌套循环中使用
i.index(primeiro):该方法会每次遍历整个音符元组查找元素索引,是O(k)的冗余操作(k为当前和弦的音符数) - 单进程运行:完全没有利用8核CPU的多核性能,算力浪费严重
优化方案
1. 替换DataFrame存储逻辑
不要在循环中操作DataFrame,先将所有计算结果存在普通Python列表中,全部计算完成后再一次性转DataFrame导出,或者直接用内置csv模块写文件,开销可以降低90%以上。
2. 简化索引和差值计算
直接用enumerate遍历音符元组同时获取索引和值,去掉冗余的index查找,差值计算直接用内置abs()函数。
3. 多进程并行计算
将不同音符数量的计算任务分配到多个进程并行执行,8核CPU可以获得接近7倍的速度提升。
4. 去掉无用分支
你需要的是1~6个音符的和弦,循环直接从range(1,7)开始即可,去掉qntd_notas=0的空元组处理逻辑。
优化后参考代码
import itertools import csv from concurrent.futures import ProcessPoolExecutor # 音符取值范围 NOTES = list(range(1, 13)) def process_chord(chord): """处理单个和弦,计算差值列表""" diffs = [] n = len(chord) for idx in range(n): first = chord[idx] for second in chord[idx+1:]: diffs.append(abs(second - first)) return [list(chord), diffs] def process_note_count(count): """处理指定音符数的所有和弦""" all_chords = itertools.product(NOTES, repeat=count) return [process_chord(c) for c in all_chords] def main(): all_results = [] # 并行处理1~6个音符的和弦 with ProcessPoolExecutor() as executor: for res in executor.map(process_note_count, range(1,7)): all_results.extend(res) # 一次性写入CSV with open("acordes_e_diferencas_TOTAL.csv", "w", newline="", encoding="utf-8") as f: writer = csv.writer(f) writer.writerow(["notas", "diferencas"]) writer.writerows(all_results) if __name__ == "__main__": main()
效果预期
上述优化后的代码在8核机器上运行,预计耗时不超过10分钟即可完成全部计算和导出。
内容的提问来源于stack exchange,提问作者user10371424
相关产品推荐
相关产品推荐

