在 C++ 中读取文件包含带有 mmap() 的浮点数
Reading file consists of float number with mmap() in C++
我正在尝试读取一个由 100000000 个浮点数组成的文件,例如 0.12345678 或 -0.1234567,由 space 分隔在 C++ 中。我用 fscanf() 读取文件,代码是这样的:
FILE *fid = fopen("testingfile.txt", "r");
if (fid == NULL)
return false;
float v;
for (int i = 0; i < 100000000; i++)
fscanf(fid, "%f", &v);
fclose(fid);
文件大小为 1199999988 字节,用 18 秒 完成读取 fscanf()。因此,我想使用mmap()来加快读取速度,代码是这样的:
#define FILEPATH "testingfile.txt"
char text[10] = {'[=11=]'};
struct stat s;
int status = stat(FILEPATH, &s);
int fd = open(FILEPATH, O_RDONLY);
if (fd == -1)
{
perror("Error opening file for reading");
return 0;
}
char *map = (char *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if (map == MAP_FAILED)
{
perror("Error mmapping the file");
return 0;
}
for (int i = 0,j=0; i < s.st_size; i++)
{
if (isspace(map[i]))
{
text[j] = '[=11=]';
j = 0;
float v = atof(text);
for (int j = 0; j < 10; j++)
text[j] = '[=11=]';
continue;
}
text[j] = map[i];
j++;
}
if (munmap(map, s.st_size) == -1)
{
return 0;
}
但是,完成阅读仍然需要大约 14.5 秒。我发现最耗时的部分是将数组转换为浮点数,耗时约 10 秒
所以我有三个问题:
有什么方法可以直接读取 float 而不是 char 或
有没有更好的方法将char数组转为float
fscanf
如何识别浮点值并读取,比atof()
.
快多了
提前致谢!
根据给出的建议,这里有两个可能的解决方案:
第一种方法有点"stupid"。由于存储的浮点数值的格式是已知的,因此无需使用 atof()
即可轻松完成从字符数组到浮点数的转换。
通过删除atof()
,只需8秒即可完成同一文件的读取和转换。
第二种方法是更改文件中浮点数的存储格式(按照 Jeremy Friesner 的建议)。浮点数值以二进制格式存储,因此不需要 mmap()
的转换部分。代码变成这样:
#define FILEPATH "myfile.bin"
int main()
{
int start_s = clock();
struct stat s;
int status = stat(FILEPATH, &s);
int fd = open(FILEPATH, O_RDONLY);
if (fd == -1)
{
perror("Error opening file for reading");
return 0;
}
float *map = (float *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if (map == MAP_FAILED)
{
perror("Error mmapping the file");
return 0;
}
for (int i = 0; i < s.st_size / 4; i++)
{
float v = map[i];
}
if (munmap(map, s.st_size) == -1)
{
return 0;
}
}
这将大大减少读取相同大小的文件所需的时间。
我正在尝试读取一个由 100000000 个浮点数组成的文件,例如 0.12345678 或 -0.1234567,由 space 分隔在 C++ 中。我用 fscanf() 读取文件,代码是这样的:
FILE *fid = fopen("testingfile.txt", "r");
if (fid == NULL)
return false;
float v;
for (int i = 0; i < 100000000; i++)
fscanf(fid, "%f", &v);
fclose(fid);
文件大小为 1199999988 字节,用 18 秒 完成读取 fscanf()。因此,我想使用mmap()来加快读取速度,代码是这样的:
#define FILEPATH "testingfile.txt"
char text[10] = {'[=11=]'};
struct stat s;
int status = stat(FILEPATH, &s);
int fd = open(FILEPATH, O_RDONLY);
if (fd == -1)
{
perror("Error opening file for reading");
return 0;
}
char *map = (char *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if (map == MAP_FAILED)
{
perror("Error mmapping the file");
return 0;
}
for (int i = 0,j=0; i < s.st_size; i++)
{
if (isspace(map[i]))
{
text[j] = '[=11=]';
j = 0;
float v = atof(text);
for (int j = 0; j < 10; j++)
text[j] = '[=11=]';
continue;
}
text[j] = map[i];
j++;
}
if (munmap(map, s.st_size) == -1)
{
return 0;
}
但是,完成阅读仍然需要大约 14.5 秒。我发现最耗时的部分是将数组转换为浮点数,耗时约 10 秒
所以我有三个问题:
有什么方法可以直接读取 float 而不是 char 或
有没有更好的方法将char数组转为float
fscanf
如何识别浮点值并读取,比atof()
. 快多了
提前致谢!
根据给出的建议,这里有两个可能的解决方案:
第一种方法有点"stupid"。由于存储的浮点数值的格式是已知的,因此无需使用 atof()
即可轻松完成从字符数组到浮点数的转换。
通过删除atof()
,只需8秒即可完成同一文件的读取和转换。
第二种方法是更改文件中浮点数的存储格式(按照 Jeremy Friesner 的建议)。浮点数值以二进制格式存储,因此不需要 mmap()
的转换部分。代码变成这样:
#define FILEPATH "myfile.bin"
int main()
{
int start_s = clock();
struct stat s;
int status = stat(FILEPATH, &s);
int fd = open(FILEPATH, O_RDONLY);
if (fd == -1)
{
perror("Error opening file for reading");
return 0;
}
float *map = (float *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if (map == MAP_FAILED)
{
perror("Error mmapping the file");
return 0;
}
for (int i = 0; i < s.st_size / 4; i++)
{
float v = map[i];
}
if (munmap(map, s.st_size) == -1)
{
return 0;
}
}
这将大大减少读取相同大小的文件所需的时间。