首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有办法让线程不那么激烈地竞争I/O资源?

有没有办法让线程不那么激烈地竞争I/O资源?
EN

Stack Overflow用户
提问于 2021-05-11 18:21:20
回答 1查看 59关注 0票数 0

我编写了以下并行测试用例,它的运行速度至少比md5sum二进制文件慢2倍:

代码语言:javascript
复制
// dependencies are md-5 = "0.9.1", rayon = "1.5.0", hex-slice = "0.1.4"

use std::{
    convert::TryInto,
    env::args_os,
    fs::File,
    io::{Error, Read},
    path::PathBuf,
};

use hex_slice::AsHex;
use md5::{self, digest::Digest};
use rayon::prelude::*;

fn main() {
    args_os()
        .skip(1)
        .collect::<Vec<_>>()
        .par_iter()
        .for_each(|path| {
            println!(
                "{:02x}  {}",
                md5sum(PathBuf::from(&path)).unwrap().plain_hex(false),
                path.to_string_lossy()
            );
        });
}

fn md5sum(path: PathBuf) -> Result<[u8; 16], Error> {
    let mut file = File::open(path)?;
    let mut ctx = md5::Md5::default();
    let mut buf = vec![0u8; 2_097_152];
    loop {
        let bytes_read = file.read(&mut buf)?;
        if bytes_read == 0 {
            break;
        }
        ctx.update(&buf[0..bytes_read]);
    }
    Ok(ctx.finalize().try_into().unwrap())
}

如果我去掉了并行性(将par_iter()改为iter()),它就会比md5sum二进制文件快一点,所以编译器和md-5crate肯定不是问题。该算法并不完全受I/O限制,因为两个md5sum进程比一个进程在两个文件上操作的速度要快一些。

测试背景:通过使用SysInternals RamMap清空工作集和备用列表,我在两次测试之间刷新了磁盘缓存。其他背景:我在WSL2中运行代码,但在Windows文件夹中对文件进行校验和。数据存储在传统的硬盘上。

我尝试了ThreadPool、使用tokio的异步读取(使用信号量的parallel+concurrent以确保没有打开太多文件)和Rayon (如上所述)。我尝试了从512KB到10MB的缓冲区大小。操作系统或驱动器控制器应该足够智能,可以尽可能快地读取数据,但它不能正常工作,可能是因为系统想要设置延迟的下限。有没有办法在并发读取的情况下获得不错的性能?

EN

回答 1

Stack Overflow用户

发布于 2021-05-11 18:21:20

不是一个完整的解决方案:我通过使用Semaphore限制I/O (不是互斥,因为在固态硬盘上我希望允许多次读取)获得了一些加速。我重新安排了代码,将读取与计算分开,但这不适合非常大的文件。

读取将是顺序的,但计算可以并行进行:

代码语言:javascript
复制
fn md5sum(io_lock: Arc<Semaphore>, path: PathBuf) -> Result<[u8; 16], Error> {
    let buf = {
        let _lock = io_lock.access();
        let mut file = File::open(path)?;
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;
        buf
    };
    Ok(md5::Md5::digest(&buf).try_into().unwrap())
}

如果能知道是否有一种方法可以让操作系统优化读取,那就更好了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67484826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档