Как ускорить бинарное чтение / запись - PullRequest
0 голосов
/ 29 октября 2018

У меня есть этот код

//N = 32;
//B = 27;
using (FileStream fs = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
    using (BinaryReader br = new BinaryReader(fs))
    {
        using (BinaryWriter bw = new BinaryWriter(fs))
        {
            for (int k = B; k < N; ++k)
            {
                Console.WriteLine(k);
                long pt = 0;
                long j = 1L << k;
                for (long i = 0; i < (1L << (N - 1)); ++i)
                {
                    long b1;
                    long b2;

                    br.BaseStream.Seek(8 * (pt), SeekOrigin.Begin);
                    b1 = br.ReadInt64();
                    br.BaseStream.Seek(8 * (j - 1), SeekOrigin.Current);
                    b2 = br.ReadInt64();

                    long t1 = b1 + b2;
                    long t2 = b1 - b2;

                    bw.BaseStream.Seek(8 * (pt), SeekOrigin.Begin);
                    bw.Write(t1);
                    bw.BaseStream.Seek(8 * (j - 1), SeekOrigin.Current);
                    bw.Write(t2);

                    pt += 1;
                    if ((pt & (j - 1L)) == 0)
                    {
                        pt += j;
                    }
                    if ((i % 100000) == 0) Console.WriteLine(i);
                }
            }
        }
    }
}

Что происходит, программа читает два длинных с разных позиций в очень большом (17 ГБ) файле, добавляет / вычитает их, а затем переписывает новые значения в те же позиции.

Из того, что я могу извлечь, наиболее эффективный способ чтения данных - это чтение большого куска в буфер и последующая работа с ним. Однако этот подход здесь не работает, потому что, основываясь на значениях pt и j , он может считывать начало и конец файла, и, конечно, я могу Не храните все 17 ГБ в памяти.

Линия

if ((i % 100000) == 0) Console.WriteLine(i);

- для отладки, между ними на моем компьютере около 2 секунд. Мне нужно, чтобы это было намного быстрее. В статье, за которой я следую, говорится, что их реализация заняла менее 30 минут для этого цикла. Есть ли более быстрая альтернатива для быстрого чтения большого числа числовых данных?

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Если я правильно понимаю, результаты записываются в те места, которые вы только что прочитали.

Таким образом, если вы измените порядок записи, первая запись будет в том же месте, откуда вы последний раз читали.

Это сократит время поиска.

Далее, это означает, что следующее чтение будет также смежным с другой записью, снова уменьшая время поиска.

Теперь основной цикл над 'i', очевидно, длинный, но я думаю, что вы могли бы:

  • Разбейте это на куски среднего размера (64М или около того может быть все, что вам нужно)
  • Выполните весь блок чтения
  • Выполните второй блок чтения
  • Выполнитевычисление в памяти для обоих блоков
  • Запишите их
0 голосов
/ 29 октября 2018

Это не совсем ответ как таковой. Тем не менее, он должен дать вам идеи о том, как конкретно вы можете ускорить это

На первый взгляд, это делится на вероятности, параллелизм и размер патрона.

Если существует высокая вероятность того, что следующее чтение / запись будет найдено в большем фрагменте, то большой размер фрагмента будет повышением производительности. В свою очередь, не нужно продолжать сканирование диска.

Если вы используете SSD , вы, вероятно, можете загружать кучу Mbs (за раз) более производительным способом, чем блок по умолчанию 4k, который он, вероятно, использует.

Кроме того, по-видимому, это можно разбить на параллельные рабочие нагрузки ... Хотя на самом деле неясно, какие изменения вам понадобятся с самого начала.

Однако, если вы действительно хотите это быстро

  • Иди и купи себе 32 гигабайта барана
  • Создать унаследованный класс Stream или, что еще лучше, просто пользовательский класс
  • Загрузите весь набор данных в память, разбитый на массивы кусков примерно в гиг.
  • Использовать прямой доступ к указателю
  • Использовать параллельные рабочие нагрузки

Если бы вы могли сделать это (и это умозрительно), вы могли бы ускорить это на много факторов быстрее. И за беспорядочную стоимость памяти в пару сотен долларов и кодирования на несколько дней.

Потрясающий комментарий от @ NPras

Вместо того, чтобы самостоятельно управлять кэшированием / разбиением оперативной памяти, вы также можете хочу взглянуть на концепцию сопоставленного с памятью файла s и пусть ОС управлять этим для вас

И из Управление отображенными в память файлами

enter image description here

...