【发布时间】:2023-03-20 17:16:01
【问题描述】:
我正在为模型做一些 Monte Carlo,并认为 Dask 可能对此非常有用。在最初的 35 个小时左右,一切都运行得相当“顺利”(除了风扇噪音给人一种计算机正在起飞的感觉)。每个模型运行大约需要 2 秒,并且有 8 个分区并行运行它。活动监视器显示 8 个 python3.6 实例。
但是,计算机已经“静默”并且 CPU 使用率(如 Spyder 中显示的那样)几乎没有超过 20%。模型运行按顺序进行(不是并行),每次运行大约需要 4 秒。这发生在今天的某个时候,当时我正在处理其他事情。我了解根据操作顺序,Dask 不会同时使用所有内核。但是,在这种情况下,实际上只需要执行一项任务(请参见下文),因此可以预期所有分区或多或少同时运行和完成。 编辑:过去整个设置已成功运行 10.000 次模拟,现在不同的是要运行近 500.000 次模拟。
编辑 2:现在它已转变为并行执行 2 个分区(而不是之前的 1 和原来的 8)。似乎有什么东西让它改变了同时处理的分区数量。
编辑 3:根据建议,我使用 dask.distributed.Client 来跟踪正在发生的事情,并在前 400 行运行它。完成后的外观图示如下。我正在努力理解 x 轴标签,将鼠标悬停在矩形上显示大约 143 秒。
因此有些问题是:
- 运行其他软件(Chrome、MS Word)和让计算机从python“收回”一些CPU之间有什么关系吗?
- 或者相反,这是否与我在某个时候运行了第二个 Spyder 实例这一事实有关?
- 甚至,计算机会以某种方式内存不足吗?但是那命令不会停止运行吗?
- ...还有其他可能的解释吗?
- 是否可以“告诉” Dask 继续努力工作,并在它仍在运行原始命令时重新使用所有 CPU 能力?
- 是否可以中断执行并保留已执行的计算?我注意到停止当前命令似乎没有多大作用。
- 是否可以在运行时查询计算的整体进度?我想知道还有多少模型运行才能知道以这种缓慢的速度完成需要多长时间。我过去曾尝试使用ProgressBar,但它一直保持在 0%,直到计算结束前几秒钟。
需要明确的是,上传模型和必要的数据会非常复杂。我没有创建一个可重复的例子,要么是因为害怕让问题变得更糟(现在模型至少还在运行......)而且因为 - 正如你现在可能知道的那样 - 我几乎不知道什么可以导致它,我不希望任何人能够重现它。我知道这不是最佳做法并提前道歉。但是,如果有人以前彻底了解过类似的事情和/或有使用 Dask 的经验,我将非常感谢您对可能发生的事情和可能的解决方法的一些想法。
运行: - macOS 10.13.6(内存:16 GB | 处理器:2.5 GHz Intel Core i7 | 4 核) - 蜘蛛3.3.1 - 达斯克 0.19.2 - 熊猫 0.23.4
如果有什么需要说清楚的,请告诉我
如果您认为它可能相关,那么脚本的主要思想是:
# Create a pandas DataFrame where each column is a parameter and each row is a possible parameter combination (cartesian product). At the end of each row some columns to store the respective values of some objective functions are pre-allocated too.
# Generate a dask dataframe that is the DataFrame above split into 8 partitions
# Define a function that takes a partition and, for each row:
# Runs the model with the coefficient values defined in the row
# Retrieves the values of objective functions
# Assigns these values to the respective columns of the current row in the partition (columns have been pre-allocated)
# and then returns the partition with columns for objective functions populated with the calculated values
# map_partitions() to this function in the dask dataframe
有什么想法吗? 这显示了脚本是多么简单:
仪表板:
更新:我采取的方法是:
- 设置大量分区(
npartitions=nCores*200)。这使得可视化进度变得更加容易。我不确定设置这么多分区是否是一种好习惯,但它的工作速度并没有太大的放缓。 - 我最终没有尝试通过
.compute()获得一个巨大的 pandas DataFrame,而是将 dask 数据帧写入 Parquet(这样每个分区都写入了一个单独的文件)。后来,将所有文件读入 dask 数据帧并compute将其写入 pandas 数据帧并不困难,如果中间出现问题,至少我不会丢失已成功处理和写入的分区。
这是它在给定点的样子:
【问题讨论】:
-
也许您的访问模式发生了变化,并且位置下降导致更多的 IO。但这只是猜测。
-
没有关于您正在运行的算法的信息,我可以假设您遇到了设计上不并行的瓶颈步骤。
-
@EliKorvigo 感谢您的输入,我知道如果没有正确的算法很难猜测。实际上只有一步:在每个分区上运行 .iterrows() 并返回更新的分区。这在过去对较少的模拟有效,因此在这种情况下,设计本身可能不是问题。我已将此信息添加到说明中以使其更清晰。
-
@sascha 也感谢您的意见,坦率地说,这些事情超出了我目前的知识范围,所以在制作任何其他 cmets 之前,我必须先查一下您的意思。
标签: python python-3.x pandas spyder dask