Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
优化大规模python字典解析,多线程_Python_Multithreading_Dictionary_Optimization_Bigdata - Fatal编程技术网

优化大规模python字典解析,多线程

优化大规模python字典解析,多线程,python,multithreading,dictionary,optimization,bigdata,Python,Multithreading,Dictionary,Optimization,Bigdata,让我们以python字典为例,其中的值是整数列表 example_dict1 = {'key1':[367, 30, 847, 482, 887, 654, 347, 504, 413, 821], 'key2':[754, 915, 622, 149, 279, 192, 312, 203, 742, 846], 'key3':[586, 521, 470, 476, 693, 426, 746, 733, 528, 565]} 假设我需要解析列表的值,我已将其实现为以下函

让我们以python字典为例,其中的值是整数列表

example_dict1 = {'key1':[367, 30, 847, 482, 887, 654, 347, 504, 413, 821],
    'key2':[754, 915, 622, 149, 279, 192, 312, 203, 742, 846], 
    'key3':[586, 521, 470, 476, 693, 426, 746, 733, 528, 565]}
假设我需要解析列表的值,我已将其实现为以下函数:

def manipulate_values(input_list):
    return_values = []
    for i in input_list:
        new_value = i ** 2 - 13
        return_values.append(new_value)
    return return_values
现在,我可以很容易地解析此字典的值,如下所示:

for key, value in example_dict1.items():
    example_dict1[key] = manipulate_values(value)
结果如下:

example_dict1 = {'key1': [134676, 887, 717396, 232311, 786756, 427703, 120396, 254003, 170556, 674028], 
     'key2': [568503, 837212, 386871, 22188, 77828, 36851, 97331, 41196, 550551, 715703], 
     'key3': [343383, 271428, 220887, 226563, 480236, 181463, 556503, 537276, 278771, 319212]}
这对小型词典很有用

我的问题是,我有一本庞大的字典,里面有数百万个键和长长的列表。如果我采用上述方法,算法的速度将会非常慢

我如何优化上述内容

(1) 多线程处理——除了传统的
线程处理
模块外,字典中是否还有更有效的多线程处理该语句的选项

(2) 更好的数据结构是否合适

我问这个问题是因为,在这种情况下,我非常困惑如何最好地进行。我看不到比字典更好的数据结构,但是字典中的for循环(然后是值列表中的for循环)非常慢。这里可能有一些被设计得更快的东西

编辑:正如你所想象的,这是一个有点像玩具的例子——所讨论的函数比x**2-13复杂一点


我更感兴趣的是如何利用一本包含数百万个键和一长串值的字典来实现价值

如果您有足够的RAM:

example_dict2 = dict(zip(example_dict1.keys(), np.array(list(example_dict1.values()))**2 -13))
>>> example_dict2
{'key1': array([134676,    887, 717396, 232311, 786756, 427703, 120396, 254003,
       170556, 674028]), 'key2': array([568503, 837212, 386871,  22188,  77828,  36851,  97331,  41196,
       550551, 715703]), 'key3': array([343383, 271428, 220887, 226563, 480236, 181463, 556503, 537276,
       278771, 319212])}

如果您有足够的RAM:

example_dict2 = dict(zip(example_dict1.keys(), np.array(list(example_dict1.values()))**2 -13))
>>> example_dict2
{'key1': array([134676,    887, 717396, 232311, 786756, 427703, 120396, 254003,
       170556, 674028]), 'key2': array([568503, 837212, 386871,  22188,  77828,  36851,  97331,  41196,
       550551, 715703]), 'key3': array([343383, 271428, 220887, 226563, 480236, 181463, 556503, 537276,
       278771, 319212])}

如果可以将所有内容存储在numpy阵列中,则处理速度会更快。为了测试可伸缩性,我将每个列表的大小增加了50万倍,结果如下:

从timeit导入timeit
将numpy作为np导入
n=500000
例如(dict1={'key1':[367,30847,482,887,654,347,504,413,821]*n,
'键2':[754915279192312203742846]*n,
'key3':[586521470476693426746733528565]*n}
def操作_值(输入_列表):
返回值=[]
对于输入列表中的i:
新的_值=i**2-13
返回\u值。追加(新的\u值)
返回值
使用您的方法:

for_with_dictionary = timeit("""
for key, value in example_dict1.items():
    example_dict1[key] = manipulate_values(value)
""", "from __main__ import example_dict1,manipulate_values ",number=5)

print(for_with_dictionary)

>>> 33.2095841
对于numpy:

numpy_broadcasting = timeit("""
array = np.array(list(example_dict1.values()))
array = array ** 2 - 13
""", "from __main__ import example_dict1, np",number=5)
print(numpy_broadcasting)

>>> 5.039885

速度有了显著的提升,至少提升了6倍。

如果您可以将所有内容存储在numpy阵列中,处理速度将更快。为了测试可伸缩性,我将每个列表的大小增加了50万倍,结果如下:

从timeit导入timeit
将numpy作为np导入
n=500000
例如(dict1={'key1':[367,30847,482,887,654,347,504,413,821]*n,
'键2':[754915279192312203742846]*n,
'key3':[586521470476693426746733528565]*n}
def操作_值(输入_列表):
返回值=[]
对于输入列表中的i:
新的_值=i**2-13
返回\u值。追加(新的\u值)
返回值
使用您的方法:

for_with_dictionary = timeit("""
for key, value in example_dict1.items():
    example_dict1[key] = manipulate_values(value)
""", "from __main__ import example_dict1,manipulate_values ",number=5)

print(for_with_dictionary)

>>> 33.2095841
对于numpy:

numpy_broadcasting = timeit("""
array = np.array(list(example_dict1.values()))
array = array ** 2 - 13
""", "from __main__ import example_dict1, np",number=5)
print(numpy_broadcasting)

>>> 5.039885


速度有了显著的提升,至少提升了6倍。

您是否有足够的内存来存储numpy数组中的所有内容?线程对您没有帮助,因为python全局解释器锁(GIL)在python级别强制执行协作多线程-一次只能运行一个线程,因此没有并行性。列表大小是否相同?人们提到了转换为numpy。如果这些列表首先是在numpy中创建的,那么效率会更高。如果使用numpy,它会释放GIL,并且您可以潜在地将处理提供给线程池。它通常不值得池管理的性能损失。你有足够的内存来存储numpy数组中的所有内容吗?线程对你没有帮助,因为python全局解释器锁(GIL)在python级别强制执行协作多线程-一次只能运行一个线程,因此没有并行性。列表大小是否相同?人们提到了转换为numpy。如果这些列表首先是在numpy中创建的,那么效率会更高。如果使用numpy,它会释放GIL,并且您可以潜在地将处理提供给线程池。它通常不值得池管理的性能损失。在这5秒钟中,有多少是转换,多少是计算?使用就地操作
array**=2,计算可以更节省空间;数组-=13
@Marcos感谢您的帮助。我很好奇这是如何翻译成更多的字典键的——事实上,字典有数百万个键。另一个问题:是否可以使用NumPy框架进行多线程处理?可以让每个线程使用一组唯一的键来尝试这一点,例如,这里的答案可能是:我最初将字典作为一个pandas字典,我使用的是
.apply()
。它太慢了。这5秒钟中有多少是转换,多少是计算?使用就地操作
array**=2,计算可以更节省空间;数组-=13
@Marcos感谢您的帮助。我很好奇这是如何翻译成更多的字典键的——事实上,字典有数百万个键。另一个问题:是否可以使用NumPy框架进行多线程处理?可以让每个线程使用一组唯一的键来尝试这一点,例如,这里的答案可能是:我最初将字典作为一个pandas字典,我使用的是
.apply()
。太慢了。