Окей, у меня странное (на мой взгляд) поведение моей программы, которое теперь сводится к простому чтению 3 массивов из довольно больших (приблизительно 24 ГБ и 48 ГБ) двоичных файлов.Структура этих файлов довольно проста, они содержат небольшой заголовок и 3 массива после: типа int, int и float, все 3 размера N, где N очень большое: 2147483648 для файла 28 ГБ и 4294967296 для 48 ГБone.
Чтобы отследить потребление памяти, я использую простую функцию, основанную на sysinfo Linux, чтобы определить, сколько свободной памяти у меня есть на каждом этапе моей программы (например, после того, как я выделил массивы дляхранить данные и при чтении файла).Вот код функции:
#include <sys/sysinfo.h>
size_t get_free_memory_in_MB()
{
struct sysinfo info;
sysinfo(&info);
return info.freeram / (1024 * 1024);
}
Теперь прямо к проблеме: странная часть заключается в том, что после чтения каждого из 3 массивов из файла с использованием стандартной функции C fread или функции чтения C ++ (нене имеет значения), и, проверяя, сколько свободной памяти у нас есть после чтения, я вижу, что объем свободной памяти сильно сокращается (примерно на edge_count * sizeof (int) для следующего примера).
fread(src_ids, sizeof(int), edges_count, graph_file);
cout << "1 test: " << get_free_memory_in_MB() << " MB" << endl;
Таким образом, после прочтения всего файла мое потребление памяти по данным sysinfo почти в 2 раза больше, чем ожидалось.Чтобы лучше проиллюстрировать проблему, я приведу код всей функции вместе с ее выводом;Пожалуйста, прочитайте его, он очень маленький и лучше проиллюстрирует проблему.
bool load_from_edges_list_bin_file(string _file_name)
{
bool directed = true;
int vertices_count = 1;
long long int edges_count = 0;
// open the file
FILE *graph_file = fopen(_file_name.c_str(), "r");
if(graph_file == NULL)
return false;
// just reading a simple header here
fread(reinterpret_cast<char*>(&directed), sizeof(bool), 1, graph_file);
fread(reinterpret_cast<char*>(&vertices_count), sizeof(int), 1, graph_file);
fread(reinterpret_cast<char*>(&edges_count), sizeof(long long), 1, graph_file);
cout << "edges count: " << edges_count << endl;
cout << "Before graph alloc free memory: " << get_free_memory_in_MB() << " MB" << endl;
// allocate the arrays to store the result
int *src_ids = new int[edges_count];
int *dst_ids = new int[edges_count];
_TEdgeWeight *weights = new _TEdgeWeight[edges_count];
cout << "After graph alloc free memory: " << get_free_memory_in_MB() << " MB" << endl;
memset(src_ids, 0, edges_count * sizeof(int));
memset(dst_ids, 0, edges_count * sizeof(int));
memset(weights, 0, edges_count * sizeof(_TEdgeWeight));
cout << "After memset: " << get_free_memory_in_MB() << " MB" << endl;
// add edges from file
fread(src_ids, sizeof(int), edges_count, graph_file);
cout << "1 test: " << get_free_memory_in_MB() << " MB" << endl;
fread(dst_ids, sizeof(int), edges_count, graph_file);
cout << "2 test: " << get_free_memory_in_MB() << " MB" << endl;
fread(weights, sizeof(_TEdgeWeight), edges_count, graph_file);
cout << "3 test: " << get_free_memory_in_MB() << " MB" << endl;
cout << "After actual load: " << get_free_memory_in_MB() << " MB" << endl;
delete []src_ids;
delete []dst_ids;
delete []weights;
cout << "After we removed the graph load: " << get_free_memory_in_MB() << " MB" << endl;
fclose(graph_file);
cout << "After we closed the file: " << get_free_memory_in_MB() << " MB" << endl;
return true;
}
Итак, ничего сложного.Прямо к выводу (с некоторыми комментариями сформировать меня после //).Во-первых, для файла на 24 ГБ:
Loading graph...
edges count: 2147483648
Before graph alloc free memory: 91480 MB
After graph alloc free memory: 91480 MB // allocated memory here, but noting changed, why?
After memset: 66857 MB // ok, we put some data into the memory (memset) and consumed exactly 24 GB, seems correct
1 test: 57658 MB // first read and we have lost 9 GB...
2 test: 48409 MB // -9 GB again...
3 test: 39161 MB // and once more...
After actual load: 39161 MB // we lost in total 27 GB during the reads. How???
After we removed the graph load: 63783 MB // removed the arrays from memory and freed the memory we have allocated
// 24 GB freed, but 27 are still consumed somewhere
After we closed the file: 63788 MB // closing the file doesn't help
Complete!
After we quit the function: 63788 MB // quitting the function doesn't help too.
Аналогично для файла на 48 ГБ:
edges count: 4294967296
Before graph alloc free memory: 91485 MB
After graph alloc free memory: 91485 MB
After memset: 42236 MB
1 test: 23784 MB
2 test: 5280 MB
3 test: 490 MB
After actual load: 490 MB
After we removed the graph load: 49737 MB
After we closed the file: 49741 MB
Complete!
After we quit the function: 49741 MB
Итак, что происходит внутри моей программы?
1) Почему во время чтения теряется так много памяти (как с использованием fread из C, так и из потоков файлов из c ++)?
2) Почему закрытие файла не освобождает потребляемую память?
3) Может быть, sysinfo показывает неверную информацию?
4) Может ли эта проблема быть связана с фрагментацией памяти?
Кстати, я запускаю свою программу насуперкомпьютерный узел, к которому у меня есть эксклюзивный доступ (так что другие люди не могут повлиять на него), и где нет стороннего приложения, которое может повлиять на мою программу.
Спасибо, что прочитали это!