Need help! Не решается задача, упираюсь в ограничения железа - страница 15

 

На конец то понял что надо, надеюсь что данный вариант окончательный.

 

Как было сказано Все достаточно просто разбивается и  паралелиться, основные этапы:

1. а. Было бы весьма полезно знать где начало и конец каждой последовательности (из-за этого предлагал еще в прошлый раз записывать их размеры в отдельный файл)

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

Далее буду рассматривать вариант 1.а. возможно он не оптимален, но мне ближе по душе. 

2. Зная размеры последовательностей и размер памяти под часть файла (500 мб) можем рассчитать размер части файла который надо скачать

3. Параллельно расчитываем коэффициенты для последовательностей, так как знаем начало и конец каждой последовательности

4. Начал и конец каждой последовательности можно хранить в мультипоточной очереди (заполнялась при расчете пункта 2)

5. Результат расчета - структура (массив  из  структуры где время и коэффициет +   номер последовательности))

6. Когда же обрабатывается половина от начального размера выделенной памяти ( 250 мб ) запускается процесс дозаписи с формированием второй очереди с началами и концами 

7. Досчитав до конца первой очереди - читаем с второй; досчитав до конца второй - читаем с первой очереди.

8. Можно организовать параллельно расчет коэффициентов и чтение с файла.

9. Но каждый результат расчета коэффициентов надо хранить, а это место, лучше их сливать сразу в ответ:

надо написать функции слияния: двух последовательностей коэффициентов в один подрезультат, двух подрезультатов в один чуть полный подрезультат

10. Процесс слияния тоже можно делать параллельно.

11. Когда же будет результат? Когда закончится  размеры последовательностей считанные с допфайла, тогда два стека станут пустыми, тогда закончится расчет коэффициентов,

тогда надо дождаться до окончания процесса слияния подрезульатов ( можно тоже через потокобезопасную очередь)

и наконец произвести слияние подрезультатов различных потоков - результат.


Вот такой вариант с максимальной загрузкой всего что можно, возможно что то и лучше - буду рад.

надо функции:

формирование последовательности коэффициентов из  входной последовательности

слияние двух последовательностей коэффициентов в один подрезультат (здесь возможные потери точности)

слияние двух подрезультатов в один чуть полный подрезультат (здесь возможные потери точности)

 
komposter:

Я думаю, что можно изобрести хитрый механизм частичной загрузки, но его надо придумать.

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

После этого найти первую сделку, попадающую в результаты, и дальше работать только со свежими данными: читать файл с нужной точки до новой актуальной даты, и каждый раз смещать сделки в массиве (получится фиксированный размер массива - Х элементов).

Это решит и проблему с многократным чтением (оно просто не нужно), и с памятью (только если сможем разместить Х миллионов сделок).

Да, таким алгоритм и будет.

  1. Ресайзим все массивы сделок до Х элементов.
  2. Устанавливаем ИскомуюДату = СтартовойДате.
  3. Открываем файл, начинаем читать, последовательно заполняя массив сделок первого прохода.
  4. Если сделки, соответствующие проходу, закончились (не набралось Х сделок), устанавливаем значение критерия = Н/А и переходим к следующему проходу.
  5. Если доходим до сделки № (Х+1), сдвигаем все предыдущие сделки назад (№1 отбрасывается, №2 становится №1, №Х+1 становится №Х).
  6. Если доходим до сделки, время открытия которой >= ИскомойДаты (в массив она не добавляется):
    • Рассчитываем значение Критерия по добавленным ранее сделкам №1 - №Х
    • Запоминаем значение Критерия
    • Запоминаем положение файлового указателя перед этой сделкой
    • Переходим к следующей последовательности
  7. Если обработана последняя последовательность:
    • Пробегаемся по массиву последовательностей и находим лучшее значение Критерия
    • Переходим в файле на запомненную позицию, в которой находится последняя сделка лучшей последовательности
    • Читаем сделку из файла, добавляем ее в массив (предыдущие сделки смещаем)
    • Запоминаем положение файлового указателя
    • Записываем сделку в файл результатов
    • Устанавливаем ИскомуюДату = Времени закрытия сделки + 1
    • Продолжаем перебор последовательностей, с той лишь оговоркой, что массивы уже заполнены, а чтение продолжается с запомненной точки.

 

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

Если нет, значит нужно добавить чтение последних Х сделок при каждом возвращении к Запомненному указателю. Тогда файл будет читаться многократно, но все равно экономно. 

Структура последовательности получается фиксированной: №№, Сделки[Х],  Критерий, ПозицияФайловогоУказателя. Ничего лишнего.

 

Осталось закодить =) 

 

А что более желательный результат:

dll или все же силами mql посчитать?

 

Да, в таком виде задача параллелится - при каждом изменении ИскомойДаты можно запускать одновременный поиск лучшего Критерия по разным частям совокупности последовательностей. Например, разделить их на 20 частей и раздать задачи 20 советникам. А они пусть читают файл, находят сделку, и передают назад только лучшую последовательность (№№, Критерий и файловую позицию).

Всем огромное спасибо!

 
ALXIMIKS:

А что более желательный результат:

dll или все же силами mql посчитать?

Лучше мкл, конечно. Да и смысла длл писать особо нет, параллелить можно и в МТ.
 

пол года не был c mql могу немного тупить, уточните если не прав:

Открываем файл, начинаем читать, последовательно заполняя массив сделок первого прохода 

вы планируете для каждого прохода отдельно производить чтение из диска? 10^6 раз читать с диска? 

Не может тут быть заминки в чтении по отдельности вместо чтения целого куска сразу? Или тут все реализовано на высшем уровне с солидной буферизацией про запас?

 Если доходим до сделки, время открытия которой >= ИскомойДаты (в массив она не добавляется):

  • Устанавливаем ИскомуюДату = Времени закрытия сделки + 1
  • Продолжаем перебор последовательностей, с той лишь оговоркой, что массивы уже заполнены, а чтение продолжается с запомненной точки.

 не вижу где у вас память освобождается, она все накапливается и накапливается.

  • Пробегаемся по массиву последовательностей и находим лучшее значение Критерия

 зачем держать целый массив для одного критерия? Можно же просто сравнивать при подсчете нового критерия и оставлять подходящий.

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

 
ALXIMIKS:

вы планируете для каждого прохода отдельно производить чтение из диска? 10^6 раз читать с диска? 

Читать все равно придется все. За один раз не получается (от начала до конца), значит будем читать по кускам (но все равно в итоге весь файл).

 

ALXIMIKS:

Не может тут быть заминки в чтении по отдельности вместо чтения целого куска сразу? Или тут все реализовано на высшем уровне с солидной буферизацией про запас?

 Читается кусок. Размер куска определяется кол-вом сделок до ИскомойДаты, которые были в конкретной последовательности.

 

ALXIMIKS:

 не вижу где у вас память освобождается, она все накапливается и накапливается.

Память выделяется однократно для массива структур последовательностей.

В структуру последовательности входит: №, Массив структур всех сделок последовательности [Х], Значение Критерия, Позиция Файлового Указателя.

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

 

ALXIMIKS:

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

В том числе для распараллеливания.

Но в рамках задачи устранение одного double-а из структуры, в которой есть массив структур сделок, погоды не делает.

 

Делюсь результатами исследований.

Бинарный кэш-файл размером 7529 МБ читается:

  • с винчестера: за 212.3 сек (35.46 МБ/сек) 
  • с RAM-диска: за 88.1 сек (85.46 МБ/сек)
Разницу назвать космической сложно, при том что винчестер у меня самый обычный (хотя, и память не скоростная).

Вывод: ускорение на чтении одного большого файла с использованием RAM-диска - около 2.5 раз.

 

Если бы файл был отсортирован по времени сделок не внутри последовательностей, а глобально (по всем последовательностям), то был бы возможен такой алгоритм:

- Рассчитываем критерий для сделки, считаем её кандидатом

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

Можно и по времени закрытия сортировать, тогда двигаемся с конца

Понятно, что для расчёта критерия файл должен содержать номер последовательности для каждой сделки.

Пересортировка такого файла вероятно тоже дело невесёлое, можно попытаться сразу записывать его "как надо". То есть не генерить по очереди последовательности целиком, а генерить по очереди по одной сделке для каждой последовательности, ну и немного кеша с интеллектом при записи использовать. Для каких=то алгоритмов генерации это конечно может оказаться неприемлемым.

 
Candid:

Если бы файл был отсортирован по времени сделок не внутри последовательностей, а глобально (по всем последовательностям), то был бы возможен такой алгоритм:

- Рассчитываем критерий для сделки, считаем её кандидатом

Допустим, я запишу такой файл (просто конвертирую текущий, пусть это и займет 15 часов компьютерного времени).

Но тут же - на первом пункте - затык. Как рассчитать критерий по последним Х сделкам последовательности, имея такой файл?

Повторюсь, Критерий нельзя рассчитать один раз, его параметры могут меняться.

Причина обращения: