我正在使用双处理器的Windows机器,并尝试使用多处理库运行几个独立的python进程。当然,我的目标是最大限度地使用两个CPU,以加快计算时间。我的机器的详细信息如下:
我使用Python 3.6执行主脚本,然后使用多处理库生成72个独立于内存的工作程序。最初,我机器的所有72个核心都以100%使用。但是,大约5-10分钟后,我的第二个CPU上的所有36个内核的使用率降低到0%,而第一个CPU上的36个内核保持在100%。我无法弄清楚为什么会这样。
关于在双处理器Windows机器中使用两个CPU,我是否缺少一些东西?如何确保充分发挥机器的潜力?作为旁注,我很好奇如果我使用Linux操作系统会有所不同吗?提前感谢愿意为此提供帮助的任何人。
我的python主脚本的表示如下:
import pandas as pd
import netCDF4 as nc
from multiprocessing import Pool
WEATHERDATAPATH = "C:/Users/..../weatherdata/weatherfile_%s.nc4"
OUTPUTPATH = "C:/Users/....outputs/result_%s.nc4"
def calculationFunction(year):
dataset = nc.Dataset(WEATHERDATAPATH%year)
# Read the data
data1 = dataset["windspeed"][:]
data2 = dataset["pressure"][:]
data3 = dataset["temperature"][:]
timeindex = nc.num2date(dataset["time"][:], dataset["time"].units)
# Do computations with the data, primarily relying on NumPy
data1Mean = data1.mean(axis=1)
data2Mean = data2.mean(axis=1)
data3Mean = data3.mean(axis=1)
# Write result to a file
result = pd.DataFrame( {"windspeed":data1Mean,
"pressure":data2Mean,
"temperature":data3Mean,},
index=timeindex )
result.to_csv(OUTPUTPATH%year)
if __name__ == '__main__':
pool = Pool(72)
results = []
for year in range(1900,2016):
results.append( pool.apply_async(calculationFunction, (year, )))
for r in results: r.get()
答案 0 :(得分:1)
事实证明问题出在NumPy上。正如this solution所解释的那样,NumPy和其他几个类似的软件包依赖于BLAS库进行数值运算。该库使用多线程来提高性能。但是由于多线程是CPU绑定的,这导致Numpy执行的许多操作(在我的原始代码中,直到中间开始,如我已指出的那样)被强制到第一个CPU上。
解决方案是关闭BLAS库的多线程功能。我不确定这是否会影响性能,但在这种情况下我认为它会没问题。幸运的是,这很容易做到,我只需要在我的python代码中直接设置一个环境变量:
import os
os.environ["OPENBLAS_MAIN_FREE"] = "1"
现在整个代码中机器都满负荷运行:)
答案 1 :(得分:0)
这可能是由于Windows 核心停车。
令人惊讶的是,似乎没有关于网络上的功能的明确描述,只有信息碎片。
基本上,涉及的内核/ CPU越多,同步开销(它的二次方)和功耗就越高。因此,Win7 +尝试使用足以满足当前工作负载的最少内核/ CPU。同样,与内核间同步相比,SMP同步具有不同的开销 - 可能更高,因为CPU需要锁定共享内存总线以执行互锁操作,完全关闭其他CPU,而内核具有更多的余地,因为没有行业标准来管理CPU内部发生的事情。
您的任务部分受CPU限制,部分受I / O约束。在PC中,批量I / O通常使用DMA完成,允许CPU在此期间切换到其他内容。因此,从理论上讲,您的工作负载可以通过比工作者更少的内核来处理。
首先,您需要检查是否属于这种情况。毕竟,也许只是某些工人已经完成而且还有一些尚未完成。
首先,您可以在加载后运行任务管理器,看看是否标记了任何核心"停放"。
然后,在步骤之间的worker函数中使用这些调试打印,以找出它当前正在运行的位置:
print("PID: %d, CPU: %d"%(os.getpid(),ctypes.windll.kernel32.GetCurrentProcessorNumber())
或者,您可以编辑标准库中的trace.py:localtrace_trace()
以显示此信息,并使用跟踪运行程序以获取更多统计信息(请注意,大量跟踪会将工作负载更改为I / O,因此请使用在解释结果时要小心。)
现在,如果它确实是核心停车场,那么就是你如何控制它。
MS不会发布这些信息 - 可能是因为他们希望自由更改信息,或者因为它太深,绝大多数用户都无法使用。HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\54533251-82be-4824-96c1-47b60b740d00\
。在值中,您会看到这是Power Settings Control Panel应用程序中处理器电源设置的注册表。Attributes
值为00000001
(最低有效位集),这意味着他们在应用程序的GUI中隐藏了。为了展示它们,你需要
由于MS没有解释哪个值有哪些(我们只有这些注册表项中的解释文本 - 如果你取消隐藏设置,它也显示在GUI中),那就太棒了关于他们在网络上的意义的混淆 - 包括来自公用事业作家。
至少,将"Processor performance core parking min cores"
设置为100%将有效禁用停车(但不是空闲状态和频率管理)。
Power and performance Tuning | Microsoft Docs表示对于服务器Windows系统,"高性能"配置文件完全禁用停车和频率限制 - 所以最可靠的方法是获取其中一个操作系统并从该配置文件中复制所有设置。