#c# #.net #.net-core #memory-leaks #hdf
Вопрос:
Я должен написать код с использованием .NET 5.0 C#, который будет генерировать файлы HDF5 для каждого из следующих случаев:
- 2D массив случайных двойников. Размер: 20M x 1K (таким образом, размер файла должен быть около 150 ГБ без сжатия)
- 2D массив случайных строк (длина каждой строки должна составлять 30 символов). Размер: 500K x 100
В первом случае проблема, с которой я столкнулся, — это проблема с оперативной памятью. Средства диагностики Visual Studio показывают, как во время работы программы увеличивается объем частной памяти, занимаемой байтами, и я не могу понять, в чем причина этого. Вот код, который я использовал:
using HDF.PInvoke;
using System;
using System.IO;
namespace HTFCalculation
{
public class Program
{
private static uint rows = 1000;
private static uint columns = 20000000;
public static void Main(string[] args)
{
Console.WriteLine("Starting program");
Write(GenerateRandomNumericArray(), false);
Console.WriteLine("Program is completed");
}
public static unsafe void Write(double[] data, bool enableZip)
{
Console.WriteLine("Generating a HDF file");
// Declaring variables.
string filePath = Directory.GetCurrentDirectory() "\result.h5";
ulong[] dims = { rows, 1 };
ulong[] maxDims = { rows, columns };
ulong[] chunkDims = { rows, 1 };
ulong[] size = new ulong[2];
ulong[] offset = new ulong[2];
// Create the data space with unlimited dimensions.
var dataspace = H5S.create_simple(dims.Length, dims, maxDims);
// Create a new file.If file exists its contents will be overwritten.
long file = H5F.create(filePath, H5F.ACC_TRUNC, H5P.DEFAULT, H5P.DEFAULT);
// Modify dataset creation properties, i.e. enable chunking.
long cparms = H5P.create(H5P.DATASET_CREATE);
int status = H5P.set_chunk(cparms, dims.Length, chunkDims);
// Set compressing parameter if needed.
if (enableZip)
{
H5P.set_filter(cparms, H5Z.filter_t.DEFLATE, 0, new IntPtr(1), new uint[] { 5 });
}
// Create a new dataset within the file using cparms creation properties.
long dataset = H5D.create(file, "data", H5T.NATIVE_DOUBLE, dataspace, 0, cparms, 0);
// Extend the dataset. This call assures that dataset is at least 1 x column count.
size[0] = rows;
size[1] = 1;
status = H5D.set_extent(dataset, size);
// Select a hyperslab.
long filespace = H5D.get_space(dataset);
offset[0] = 0;
offset[1] = 0;
status = H5S.select_hyperslab(filespace, H5S.seloper_t.SET, offset, null, dims, null);
// Write the data to the hyperslab.
fixed (double* dataPtr = data)
{
status = H5D.write(dataset, H5T.NATIVE_DOUBLE, dataspace, filespace, H5P.DEFAULT, new IntPtr(dataPtr));
}
for (int i = 1; i < columns; i )
{
// Extend the dataset. Adding row.
size[1] ;
status = H5D.set_extent(dataset, size);
// Select a hyperslab. Increasing row offset.
filespace = H5D.get_space(dataset);
offset[1] ;
status = H5S.select_hyperslab(filespace, H5S.seloper_t.SET, offset, null, dims, null);
// Write the data to the hyperslab.
fixed (double* dataPtr = data)
{
status = H5D.write(dataset, H5T.NATIVE_DOUBLE, dataspace, filespace, H5P.DEFAULT, new IntPtr(dataPtr));
}
}
// Close/release resources.
H5D.close(dataset);
H5S.close(dataspace);
H5S.close(filespace);
H5F.close(file);
Console.WriteLine("HDF file is generated");
}
public static double[] GenerateRandomNumericArray()
{
Console.WriteLine("Preparing data array");
Random rnd = new();
double[] result = new double[rows];
for (int i = 0; i < rows; i )
{
result[i] = rnd.NextDouble();
}
Console.WriteLine("Array is readyn");
return resu<
}
}
}
Это довольно хорошо работает для файлов меньшего размера, но терпит неудачу, когда я пытаюсь записать файлы такого большого размера. Есть ли какие-либо советы, как я могу это улучшить? Я уже пытался записать каждый сгенерированный случайный массив в отдельный набор данных, создавая и закрывая каждый набор данных в каждой итерации цикла, но это ничего не меняет.
Другой вопрос заключается в том, как записать массив 2D-строк (длиной 30 символов) в файл HDF5? H5D.write()
метод требует IntPrt
в качестве последнего параметра, поэтому я не нашел никакого способа сделать это.
Я также могу рассмотреть возможность использования разных библиотек, если они решат оба вопроса.
Заранее благодарю вас!