我有一个转换非常大的矩阵的C ++程序。矩阵太大而无法保存在内存中,因此我将每列写入单独的临时文件,然后在处理完整个矩阵后连接临时文件。但是,我现在发现我遇到了打开临时文件太多的问题(即操作系统不允许我打开足够的临时文件)。是否有系统可移植方法来检查(并希望更改)允许的最大打开文件数?
我意识到我可以关闭每个临时文件并仅在需要时重新打开,但我担心这样做会对性能产生影响。
我的代码如下工作(伪代码 - 不保证可以正常工作):
int Ncol=5000; // For example - could be much bigger.
int Nrow=50000; // For example - in reality much bigger.
// Stage 1 - create temp files
vector<ofstream *> tmp_files(Ncol); // Vector of temp file pointers.
vector<string> tmp_filenames(Ncol); // Vector of temp file names.
for (unsigned int ui=0; ui<Ncol; ui++)
{
string filename(tmpnam(NULL)); // Get temp filename.
ofstream *tmp_file = new ofstream(filename.c_str());
if (!tmp_file->good())
error("Could not open temp file.\n"); // Call error function
(*tmp_file) << "Column" << ui;
tmp_files[ui] = tmp_file;
tmp_filenames[ui] = filename;
}
// Stage 2 - read input file and write each column to temp file
ifstream input_file(input_filename.c_str());
for (unsigned int s=0; s<Nrow; s++)
{
int input_num;
ofstream *tmp_file;
for (unsigned int ui=0; ui<Ncol; ui++)
{
input_file >> input_num;
tmp_file = tmp_files[ui]; // Get temp file pointer
(*tmp_file) << "\t" << input_num; // Write entry to temp file.
}
}
input_file.close();
// Stage 3 - concatenate temp files into output file and clean up.
ofstream output_file("out.txt");
for (unsigned int ui=0; ui<Ncol; ui++)
{
string tmp_line;
// Close temp file
ofstream *tmp_file = tmp_files[ui];
(*tmp_file) << endl;
tmp_file->close();
// Read from temp file and write to output file.
ifstream read_file(tmp_filenames[ui].c_str());
if (!read_file.good())
error("Could not open tmp file for reading."); // Call error function
getline(read_file, tmp_line);
output_file << tmp_line << endl;
read_file.close();
// Delete temp file.
remove(tmp_filenames[ui].c_str());
}
output_file.close();
非常感谢提前!
亚当
答案 0 :(得分:2)
至少有两个限制:
ulimit
更改限制,在sysadmin允许的范围内更好的解决方案是避免有这么多打开的文件。在我自己的一个程序中,我编写了一个围绕文件抽象的包装器(这是在Python中,但原理在C中是相同的),它跟踪每个文件中的当前文件位置,并根据需要打开/关闭文件,保留一组当前打开的文件。
答案 1 :(得分:1)
没有可移植的方法来更改打开文件的最大数量。这样的限制往往是由操作系统强加的,因此也是特定于操作系统的。
您最好的办法是减少任何时候打开的文件数量。
答案 2 :(得分:1)
您可以将输入文件规范化为临时文件,以使每个条目占用相同数量的字符。您甚至可以考虑将该临时文件保存为二进制文件(每个数字使用4/8字节而不是每个十进制数字1个字节)。这样,您可以从矩阵中的坐标计算文件中每个条目的位置。然后,您可以通过std::istream::seekg访问特定条目,而不必担心打开文件数量的限制。
答案 3 :(得分:0)
如何制作1个大文件而不是许多小型临时文件? Seek是一项廉价的操作。无论如何,你的列应该都是相同的大小。您应该能够将文件指针放在需要它的地方。
// something like...
column_position = sizeof(double)*Nrows*column ;
is.seekg(column_position) ;
double column[Nrows] ;
for( i = 0 ; i < Nrows ; i++ )
is >> column[i] ;
答案 4 :(得分:0)
“矩阵太大而无法容纳在内存中”。但是,矩阵很可能适合您的地址空间。 (如果矩阵不适合2 ^ 64字节,你需要一个非常令人印象深刻的文件系统来保存所有这些临时文件。)所以,不要担心临时文件。让操作系统处理交换到磁盘的工作方式。您只需要确保以交换友好的方式访问内存。在实践中,这意味着您需要具有一些参考地点。但是使用16 GB的RAM,你可以有大约400万页的RAM映射。如果你的columsn数量明显小于那个,那么应该没有问题。
(不要为此使用32位系统;这不值得痛苦)