C++多线程加速文件数据传输无效果,求问题排查与优化方案
问题描述
本人为C++初学者,编写代码将input.txt中的189156个数字传输至test.txt,单线程执行耗时约23秒。尝试使用4个线程各处理1/4数据以提升速度,但执行后耗时无变化。附上代码如下:
// This program reads data from a file into an array. #include <iostream> #include <fstream> // To use ifstream #include <vector> #include <thread> using namespace std; void test(int start, int end) { std::vector<int> numbers; ifstream inputFile("input.txt"); // Input file stream object // Check if exists and then open the file. if (inputFile.good()) { // Push items into a vector int current_number = 0; while (inputFile >> current_number) { numbers.push_back(current_number); } // Close the file. inputFile.close(); // Display the numbers read: cout << "The numbers are: "; for (int count = start ; count < end; count++) { cout << numbers[count] << " " ; std::ofstream ofs; ofs.open("test.txt", std::ofstream::out | std::ofstream::app); ofs << numbers[count] << endl; ofs.close(); } cout << endl; } else { cout << "Error!"; _exit(0); } } int main() { std::thread worker1(test, 0, 50000); std::thread worker2(test, 50000, 100000); std::thread worker3(test, 100000, 150000); std::thread worker4(test, 150000, 189156); worker1.join(); worker2.join(); worker3.join(); worker4.join(); return 0; }
请问该场景是否适合使用多线程?若适合,请指出代码中的错误;若不适合,请给出正确的提速方法。
问题分析与解答
是否适合多线程?
这个场景不适合用多线程提速。因为文件读写属于磁盘IO密集型任务,磁盘(尤其是机械硬盘)的并行读写能力非常有限,多线程不仅无法发挥并行优势,反而会因为重复IO、资源竞争带来额外开销,甚至拖慢执行速度。
代码中的核心错误
- 重复读取输入文件:每个线程都完整读取了一遍
input.txt,相当于总共读了4次文件,这是极大的资源浪费,直接抵消了多线程的可能收益 - 频繁打开/关闭输出文件:每个线程在循环里每写一个数字就打开、关闭一次
test.txt,频繁的文件IO操作会大幅增加耗时 - 无保护的并发写文件:多个线程同时往
test.txt追加内容,即使使用app模式,也可能导致输出内容乱序或部分数据丢失,同时增加磁盘IO的竞争冲突
正确的提速方法
针对IO密集型的文件转写任务,优化核心是减少IO次数、提升单次IO的吞吐量,推荐以下方案:
方案1:单线程优化(最有效)
一次性读取全部数据到内存,再一次性写入输出文件,避免频繁IO操作:
#include <iostream> #include <fstream> #include <vector> using namespace std; int main() { vector<int> numbers; ifstream inputFile("input.txt"); if (!inputFile.is_open()) { cout << "Error opening input file!" << endl; return 1; } // 一次性读取所有数据到内存 int num; while (inputFile >> num) { numbers.push_back(num); } inputFile.close(); // 一次性打开输出文件,写入所有数据 ofstream outputFile("test.txt"); if (!outputFile.is_open()) { cout << "Error opening output file!" << endl; return 1; } for (int n : numbers) { outputFile << n << '\n'; // 用'\n'替代endl,减少缓冲区强制刷新 } outputFile.close(); return 0; }
方案2:分块读写(适合超大型文件)
如果文件过大无法一次性载入内存,可以采用大分块的方式读写,减少IO次数:
#include <iostream> #include <fstream> #include <vector> using namespace std; const int BLOCK_SIZE = 10000; // 每次读取10000个数字 int main() { ifstream inputFile("input.txt"); if (!inputFile.is_open()) { cout << "Error opening input file!" << endl; return 1; } ofstream outputFile("test.txt"); if (!outputFile.is_open()) { cout << "Error opening output file!" << endl; return 1; } vector<int> block(BLOCK_SIZE); int count; while (true) { count = 0; // 读取一个块的数据 while (count < BLOCK_SIZE && inputFile >> block[count]) { count++; } if (count == 0) break; // 写入这个块的数据 for (int i = 0; i < count; i++) { outputFile << block[i] << '\n'; } } inputFile.close(); outputFile.close(); return 0; }
额外优化建议
- 避免使用
endl:endl会强制刷新缓冲区,增加IO次数;改用'\n',由系统自动管理缓冲区刷新时机 - 增大文件流缓冲区:可以用
rdbuf()->pubsetbuf()手动设置更大的缓冲区,进一步减少底层IO操作次数
内容的提问来源于stack exchange,提问作者ZIKO
相关产品推荐
相关产品推荐

