提问人:danula godagama 提问时间:9/25/2023 更新时间:9/25/2023 访问量:63
为多线程应用程序使用多个文件流读取同一文件
Reading the same file using multiple file streams for multithread applications
问:
问题背景:我有一个大型二进制文件,其中包含具有独特结构的数据。这些数据的一个单位称为“事件”。每个事件有 32016 个字节,单个文件包含大约 400000 个事件,使文件大小为 ~12 GB。我正在编写一个程序来处理事件,并尝试使用多线程方法,其中多个线程读取文件的不同段(让每个线程使用自己的文件流)。
问题是 fseek 无法找到文件的正确位置。以下是最小可重现的示例。该程序读取一个包含473797事件的二进制文件,计划使用 20 个胎面,而每个胎面使用不同的文件流。
#include <iostream>
#include <stream>
#include <errno.h>
#include <string.h>
using namespace std;
int main(){
FILE *segment[20];
int ret=0;
int eventsPerThread=473797/20;
int eventSize=8004;
for(int k=0;k<20;++k){
segment[k]=fopen("Datafile_367.bin","rb");
if(segment[k]==NULL){
std::cout<<"file stream is NULL!"<<k<<"\n";
}
ret=fseek(segment[k],eventsPerThread*eventSize*4*k,SEEK_SET);
std::cout<<ret<<":::"<<strerror(errno)<<"\n";
}
return 0;
}
以下是输出。fseek 有时成功,有时返回 0,而在其他时候失败,错误代码为 22(无效参数)。
0:::Success
0:::Success
0:::Success
-1:::Invalid argument
-1:::Invalid argument
-1:::Invalid argument
0:::Invalid argument
0:::Invalid argument
0:::Invalid argument
-1:::Invalid argument
-1:::Invalid argument
-1:::Invalid argument
0:::Invalid argument
0:::Invalid argument
0:::Invalid argument
-1:::Invalid argument
-1:::Invalid argument
0:::Invalid argument
0:::Invalid argument
0:::Invalid argument
对 fseek() 函数的这种行为有什么解释吗?
(请注意,最小可重现的例子是单胎面,一旦程序开始读取事件,就会发生多线程)
答:
3赞
the busybee
9/25/2023
#1
错误是偏移量计算中的溢出。您使用 ,它显然是 4 个字节宽。 对于此宽度2147483647。int
INT_MAX
我看看:
k | eventsPerThread * eventSize * 4 * k |
溢出int |
返回值fseek() |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 758427024 | 758427024 | 0 |
2 | 1516854048 | 1516854048 | 0 |
3 | 2275281072 | -2019686224 | -1 |
4 | 3033708096 | -1261259200 | -1 |
5 | 3792135120 | -502832176 | -1 |
6 | 4550562144 | 255594848 | 0 |
7 | 5308989168 | 1014021872 | 0 |
: | : | : | : |
由于溢出,结果变得消极,并且对此不满意。int
fseek()
首先,确保 s 的宽度超过 4 个字节。然后将乘法的至少一个操作数更改为 。例如像这样.long
long
eventsPerThread * eventSize * 4L * k
最后说明:考虑使用更多空格来使代码更具可读性。
评论
1赞
nielsen
9/25/2023
如果代码依赖于超过 4 个字节宽的 longs,那么最好将该假设构建到代码本身中。例如:._Static_assert(sizeof(long)>4, "Long is not so long");
评论
mmap