40000×40000布尔矩阵读写性能优化求助
老兄,你这代码跑超1小时完全是逐字节读取+频繁手动移动文件指针在拖后腿啊!40000×40000的矩阵有16亿个元素,这么折腾磁盘IO,它能快才怪。给你几个针对性的优化方案,保证速度能提好几个数量级:
1. 抛弃逐字节操作,改用批量IO
你现在的写法相当于每次去超市只买一颗糖,还要每次重新排队结账——磁盘IO是按“块”(比如4KB、8KB甚至更大)高效处理的,单字节读取+手动fseek会触发大量不必要的系统调用,把磁盘性能浪费到极致。
改成批量读取大缓冲区再解析的方式,比如:
void get_grid_values_file(bool *grid, int n, int m, char *input_filename){ FILE *in_file = fopen(input_filename, "rb"); // 一定要用二进制模式打开! if (!in_file) { // 这里加错误处理,比如perror("Failed to open file"); return; } const size_t total_elements = (size_t)n * m; char buffer[65536]; // 64KB缓冲区,可根据系统调整大小 size_t bytes_read; size_t current_idx = 0; // 批量读取缓冲区,再逐个解析到grid数组 while ((bytes_read = fread(buffer, 1, sizeof(buffer), in_file)) > 0 && current_idx < total_elements) { for (size_t i = 0; i < bytes_read && current_idx < total_elements; i++) { // 假设文件里是'0'/'1'字符,转成bool值 grid[current_idx++] = (buffer[i] == '1'); } } fclose(in_file); }
2. 用二进制模式直接读写(如果文件本身是二进制的)
如果你的输入文件不是存成文本格式的0/1,而是直接用二进制存储的布尔值(每个占1字节),那效率能再上一个台阶——直接跳过字符解析的步骤,整块读写:
// 读取 fread(grid, sizeof(bool), total_elements, in_file); // 写入同理 void write_grid_values_file(bool *grid, int n, int m, char *output_filename){ FILE *out_file = fopen(output_filename, "wb"); if (!out_file) { /* 错误处理 */ } const size_t total_elements = (size_t)n * m; fwrite(grid, sizeof(bool), total_elements, out_file); fclose(out_file); }
这种写法几乎能达到磁盘的极限读写速度。
3. 别再手动
fseek了! 原代码里的fseek(in_file, k, SEEK_SET)完全是多余的——每次调用fread/fgetc后,文件指针会自动往后移动,不需要手动定位。这额外的fseek调用会触发大量系统开销,直接删掉就行。
4. 内存访问优化(可选)
如果grid数组是行优先存储的,尽量保证你的读写顺序和内存布局一致(也就是按行遍历),避免CPU缓存失效。不过在IO密集型的场景里,这个影响不如前三点大,但聊胜于无。
内容的提问来源于stack exchange,提问作者Cees Mandjes
相关产品推荐
相关产品推荐

