我有一个采样应用程序,它每秒获取250,000
个样本,将它们缓冲在内存中,并最终附加到pandas
提供的HDFStore
。总的来说,这很好。但是,我有一个线程运行并不断清空数据采集设备(DAQ
),它需要定期运行。大约一秒钟的偏差会使事情破裂。以下是观察到的时间安排的极端情况。Start
表示DAQ
读取开始,Finish
表示完成时,IO
表示HDF写入(两个DAQ
和{
Start : 2016-04-07 12:28:22.241303
IO (1) : 2016-04-07 12:28:22.241303
Finish : 2016-04-07 12:28:46.573440 (0.16 Hz, 24331.26 ms)
IO Done (1) : 2016-04-07 12:28:46.573440 (24332.39 ms)
如您所见,执行此写入操作需要24秒(典型的写入时间约为40毫秒)。我写的硬盘没有负载,所以这个延迟不应该是由争用引起的(它在运行时大约有7%的利用率)。我已禁用对HDFStore
写入的索引。我的应用程序运行许多其他线程,所有线程都打印状态字符串,因此IO任务似乎阻塞了所有其他线程。我花了相当长的时间来逐步检查代码,找出哪里的速度变慢了,而且它总是在一个C扩展提供的方法中,这就引出了我的问题。。在
下面是一个您可以运行的示例来查看问题:
^{pr2}$您将得到类似于以下内容的输出:
IO Done : 2016-04-08 10:51:14.100479 (3.63 ms, 470)
Dummy Thread : 2016-04-08 10:51:14.101484 (12 ms)
IO Done : 2016-04-08 10:51:14.104475 (3.01 ms, 471)
Dummy Thread : 2016-04-08 10:51:14.576640 (475 ms)
IO Done : 2016-04-08 10:51:14.576640 (472.00 ms, 472)
Dummy Thread : 2016-04-08 10:51:14.897756 (321 ms)
IO Done : 2016-04-08 10:51:14.898782 (320.79 ms, 473)
IO Done : 2016-04-08 10:51:14.901772 (3.29 ms, 474)
IO Done : 2016-04-08 10:51:14.905773 (2.84 ms, 475)
IO Done : 2016-04-08 10:51:14.908775 (2.96 ms, 476)
Dummy Thread : 2016-04-08 10:51:14.909777 (11 ms)
答案是不,这些作家不会发布GIL。请参阅文档here。我知道您实际上并不是在尝试使用多个线程来编写代码,但这应该会提示您。当写操作发生时,有一些强锁被持有,以防止多次写入。}都将此作为HDF5标准的一部分。在
PyTables
和{你可以看一下SWMR,尽管熊猫不直接支持它。
PyTables
文档here和here指向解决方案。这些通常涉及到有一个单独的进程从队列中提取数据并将其写入。在在任何情况下,这通常是一个更具伸缩性的模式。在
感谢您提供工作代码。我修改了它以获得一些洞察力,然后创建了 使用多处理的修改版本。在
修改的线程版本
所有的修改只是为了获取更多的信息,没有概念上的改变。一切合而为一 文件
mthread.py
,并逐部分注释。在通常进口:
^{pr2}$write_samples
得到了一些日志记录:begin_io
获得最大延迟,超过该时间将导致警告日志条目:dummy_thread
被修改为正确停止,并且如果花费太长时间,也会发出警告:最后我们称之为一切。请随意修改日志级别,}说明了更多。在
WARNING
只显示了过多的时间,INFO
和{运行代码,我得到的结果如您所述:
从这些值可以清楚地看出,虽然
begin_io
非常繁忙且延迟(可能是在数据期间) {cd4}被延迟的时间也几乎相同。在多处理版本-工作良好
我修改了代码以在多个进程中运行,并且从那时起,它确实没有阻止
dummy_thread
。在多处理代码如下:
结论
将数据写入HDF5文件确实会阻塞其他线程,并且需要多处理版本。在
如果您希望
dummy_thread
做一些实际的工作(比如收集要存储的数据),那么您希望 将数据从这里发送到HDF5序列化程序,您将不得不进行某种消息传递-使用multiprocessing.Queue
,Pipe
或可能使用ZeroMQ(例如推拉套接字 配对)。使用ZeroMQ,您甚至可以在另一台计算机上保存数据。在编辑/警告:如果代码有时无法保存数据,我将其用于测量性能,而不是防水。当Ctrl-C在处理过程中,有时我得到损坏的文件。我认为这个问题超出了这个问题的范围(这个问题应该通过仔细停止运行进程来解决)。在
相关问题 更多 >
编程相关推荐