我正在为嵌入式 linux 编写一个应用程序,其中 5% 的处理器时间用于读取文件,95% 用于处理文件。如果我在一个线程中读取文件并继续在另一个线程中处理,我可以获得一些性能改进吗?
我正在读取支持 DMA 的 mmc 卡。文件大小为 20mb,以 2 kb 为单位。我将从读取器线程中对块进行排队,并在处理器线程中对其进行处理。因此,仅在从队列中插入和删除时需要线程同步。
我正在为 ARM9 编程。
什么应该是快速的单线程/多线程。
我正在为嵌入式 linux 编写一个应用程序,其中 5% 的处理器时间用于读取文件,95% 用于处理文件。如果我在一个线程中读取文件并继续在另一个线程中处理,我可以获得一些性能改进吗?
我正在读取支持 DMA 的 mmc 卡。文件大小为 20mb,以 2 kb 为单位。我将从读取器线程中对块进行排队,并在处理器线程中对其进行处理。因此,仅在从队列中插入和删除时需要线程同步。
我正在为 ARM9 编程。
什么应该是快速的单线程/多线程。
我建议不要使用其他线程。而是使用 posix_fadvise() 告诉 Linux 提前读取更多文件。当您的程序处理数据时,内核可以通过 DMA 读取文件。
这假设内核有足够的空闲内存用于数据缓冲。如果您的数据处理正在使用所有内存,那么内核将忽略 posix_fadvise()。
您需要的确切调用如下所示:
while( 1 ) {
ret = read(fd, buffer, 2*1024);
if( ret < 0 ) abort();
if( ret == 0 ) break;
if( ret != 2*1024 ) abort();
pos += ret;
ret = posix_fadvise(fd, pos, 8*1024, POSIX_FADV_WILLNEED);
if( ret ) abort();
process(buffer);
}
如果您按顺序读取数据,则额外的线程可能不值得,因为内核将提前读取文件并将内容缓存在内存中。内存映射文件,除非您正在为嵌入式系统编写(MMC 是内存映射的系统),变化很小(文件必须在某个时候加载到内存中,这些加载只会由尝试读取而不是通过显式调用触发)。
现在,当您调用 read 时,您的程序会在读取数据时阻塞。然后它在完成后再次启动,我认为您的处理代码会接管。它被阻塞的时间不会通过“时间”显示为“cpu时间”,因为在此期间进程处于睡眠状态。(这取决于 DMA 是否可用)。
您可能会在整个程序中显示读取该文件所需的时间增加了挂钟,但您的 cpu 时间不会下降(并且可能由于同步而上升)。
您需要确定几件事。
这两项活动可以同时进行吗?如果硬件/架构将导致处理线程阻塞另一个线程,那么将没有任何收益。
您可以预期的最大收益为 5%,(基于 Amdhal 定律)。编码的复杂性值得吗?
我建议寻找更有效的文件处理方式。仔细看看处理线程在做什么,看看。
唯一确定的方法就是尝试一下。但听起来好像你需要你的处理器来读取处理器需要的文件块。由于您受处理器限制,因此您可以预期的最大改进是读取所需的 5% 时间。
两个线程需要一个内存缓冲区来保存下一个文件块,以便它可以立即用于处理,并且许多嵌入式系统的可用内存非常有限。
您可能会从能够在读取过程中处理数据中获得一些改进,但也必然会有一些开销。与任何优化问题一样,测量是关键。
真正的问题是是否值得实施一些措施来衡量差异。对于 5% 的最大收益,我怀疑答案是否定的,但这取决于你的 5% 的潜力与你的时间相比价值多少。
您的平台是否支持内存映射文件?这将允许您将读数留给 O/S,它可能做得很好。