我有一个采样应用程序,它获取250,000
每秒采样,将它们缓冲在内存中并最终附加到HDFStore
由...提供pandas
。总的来说,这很棒。但是,我有一个线程运行并不断清空数据采集设备(DAQ
)并且它需要定期运行。大约一秒的偏差往往会破坏东西。以下是观察到的时间的极端情况。Start
表示一个DAQ
读开始,Finish
是当它完成时,并且IO
表示 HDF 写入(两者DAQ
and IO
发生在单独的线程中)。
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 毫秒)。我正在写入的 HDD 没有负载,因此这种延迟不应由争用引起(运行时利用率约为 7%)。我已禁用索引HDFStore
写道。我的应用程序运行许多其他线程,所有这些线程都打印状态字符串,因此 IO 任务似乎正在阻塞所有其他线程。我花了相当多的时间逐步浏览代码来找出速度变慢的地方,并且它总是在 C 扩展提供的方法内,这引出了我的问题..
- Python(我使用的是 3.5)可以抢占 C 扩展中的执行吗?并发性:用 C/C++ 编写的 Python 扩展是否受到全局解释器锁的影响? https://stackoverflow.com/questions/651048/concurrency-are-python-extensions-written-in-c-c-affected-by-the-global-inter似乎表明除非扩展明确产生,否则不会。
- Pandas 的 HDF5 C 代码是否实现了 I/O 的任何让步?如果是这样,这是否意味着延迟是由于 CPU 受限任务造成的?我已禁用索引。
- 关于如何获得一致的时间安排有什么建议吗?我正在考虑将 HDF5 代码移至另一个进程中。不过,这只在一定程度上有帮助,因为无论如何我都无法真正容忍大约 20 秒的写入,尤其是当它们不可预测时。
您可以运行以下示例来查看问题:
import pandas as pd
import numpy as np
from timeit import default_timer as timer
import datetime
import random
import threading
import time
def write_samples(store, samples, overwrite):
frame = pd.DataFrame(samples, dtype='float64')
if not overwrite:
store.append("df", frame, format='table', index=False)
else:
store.put("df", frame, format='table', index=False)
def begin_io():
store = pd.HDFStore("D:\\slow\\test" + str(random.randint(0,100)) + ".h5", mode='w', complevel=0)
counter = 0
while True:
data = np.random.rand(50000, 1)
start_time = timer()
write_samples(store, data, counter == 0)
end_time = timer()
print("IO Done : %s (%.2f ms, %d)" % (datetime.datetime.now(), (end_time - start_time) * 1000, counter))
counter += 1
store.close()
def dummy_thread():
previous = timer()
while True:
now = timer()
print("Dummy Thread : %s (%d ms)" % (datetime.datetime.now(), (now - previous) * 1000))
previous = now
time.sleep(0.01)
if __name__ == '__main__':
threading.Thread(target=dummy_thread).start()
begin_io()
您将得到类似于以下内容的输出:
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)