优化 Dict values(List) 乘法

Optimize Dict values(List) Multiplication

我有两个字典元素如下:初始(25 个键值对)结果(100 个键值对)

Initial: {0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0],....... 24: [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0]}

Results: {'0': [360, 0, 0, 0, 0, 1, 0, 0, 3, 3, 0, 0, 15, 0, 14, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 3, 3, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 2, 0, 1, 0, 0, 3, 1, 0, 1, 0, 0, 0, 1, 2, 0, 2, 0, 0, 0, 137, 21, 78, 65, 241, 31, 30, 88, 152, 3, 13, 67, 31, 145, 132, 37, 1, 107, 120, 171, 39, 35, 31, 8, 24, 0, 0, 0, 0, 0],......'100': [183, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 2, 8, 1, 3, 1, 0, 3, 3, 0, 1, 1, 3, 2, 1, 1, 4, 0, 2, 1, 3, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 76, 10, 25, 33, 121, 14, 6, 40, 62, 2, 5, 34, 23, 66, 61, 28, 1, 56, 46, 69, 23, 10, 14, 1, 13, 1, 0, 0, 0, 0]}

在每次迭代中,我将 Results 字典的每个值乘以 Initial 字典中的一个值,并调用一个传递乘积的函数,该乘积将获取另一个值,然后我遍历整个 Initial 字典值。我正在使用以下代码执行此操作:

for z in Initial.keys():
        for i in sorted(Results.keys()):
            result = {i :[x*y for x, y in zip(Initial[z], Results[i])]}  

一个完整的循环大约需要 1 分钟,我将需要执行至少 5000 个循环才能观察最终结果。任何关于改进 performance/Optimization 代码的建议将不胜感激。

您的值是列表,因此您必须一次乘以一个元素。您可以先将您的值(列表)转换为数组,然后使用向量化乘法,从而消除列表理解和元素明智乘法的使用,如下所示

# Converting the values to arrays once for all
Initial = {k:np.array(v) for k,v in Initial.items()}
Results = {k:np.array(v) for k,v in Results.items()}

# Now just using vectorized multipliction
for z in Initial.keys():
    for i in sorted(Results.keys()):
        result = {i :Initial[z] * Results[i]}  

由于您没有提供完整的数据,我对您的代码进行了约 100 万次迭代,发现矢量化代码速度更快。在您的原始数据上尝试一下,看看是否可以加快速度(您应该这样做)。


比较时间的测试用例

您的列表理解版本用了 1 分 6 秒

for ii in range(500000):
    for z in Initial.keys():
        for i in sorted(Results.keys()):
            result = {i :[x*y for x, y in zip(Initial[z], Results[i])]}  

以下矢量化操作耗时 2.9 秒

for ii in range(500000):
    for z in Initial.keys():
        for i in sorted(Results.keys()):
            result = {i :Initial[z] * Results[i]}