我正在开发一个nvme-cli的测试工具(用c语言编写,可以在linux上运行)。
我有兴趣使用“t”个线程重复 nvme 命令“r”次。
下面的代码与线程一起重复每个命令,但这里的问题是与串行执行相比,并行执行时间非常长。
我发现的原因是
err = nvme_identify(fd, 0, 1, data);
依次调用系统调用ioctl();
#pragma omp parallel for num_threads(5)
for(i=0; i<rc; i++){
err = nvme_identify(fd, 0, 1, data);
if (!err) {
if (rf->fmt == BINARY)
d_raw((unsigned char *)&rf->ctrl, sizeof(rf->ctrl));
else if (rf->fmt == JSON)
json_nvme_id_ctrl(data, flags, 0);
else {
printf("NVME Identify Controller:\n");
__show_nvme_id_ctrl(data, flags, 0);
}
}
else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
else
perror("identify controller");
那么我可以知道如何使用 openmp 或 pthreads 获得真正的并行性吗?
最佳答案
您当然可以调用system calls (在 syscalls(2) 中列出)来自不同的线程(否则将不可能编写在多个线程上执行 IO 的程序,就像大多数多线程 Web 服务器那样)。
但是,某些ioctl
(或其他奇怪的系统调用)可能会阻塞或需要很长时间(几秒或十分之一秒)才能执行。举一个很好的例子,弹出 CDROM 托盘是由一些 ioctl
完成的,并且需要一些可见的时间(可能是半秒)来执行(因为这是一些机械 Action )。
我猜测NVME与SSD技术有关,某些操作很慢(因为硬件本身很慢)。您的瓶颈可能是硬件本身,那么任何类型的并行化都无济于事。可能会发生这种情况 - 我真的不知道 - 您可能在多个线程中使用相同的 ioctl
(在同一个文件描述符上),但内核会序列化其处理.
当内核执行一些阻塞或长时间运行的ioctl
(或任何其他系统调用)时,它使用其调度程序来运行其他任务(进程或线程)并执行一些locking 。那么您的进程处于 D
状态(参见 proc(5) 和 /proc/self/stat
或 /proc/1234/stat
了解进程pid 1234),甚至不处理被推迟的信号(参见 signal(7) )。
关于我可以使用 openmp 或 pthreads 通过不同线程调用相同的系统调用吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47406728/