Для ускорения оптимизации ТС делают следующее
- Увеличивают количество параллельных вычислительных потоков.
- Пробуют разные компиляторы.
- Переписывают код под особенности железа (OpenCL, GPU и т.д.).
- Пробуют разные алгоритмы оптимизации.
- Уменьшают количество входных данных (цены, календарь и т.д.).
- Заменяют внутренние алгоритмы на более оптимальные по вычислительным ресурсам.
Последний пункт называют алгоритмической оптимизацией.
Реальная оптимизация.
А может ли реальная (вычислительная) оптимизация ускорить оптимизацию? Звучит, как масло масленное.
Ниже приведу пример, который, возможно, кого-то натолкнет на полезные идеи ускорения расчетов в своих ТС.
Пример.
Хотелось привести не гипотетический, а реальный пример, но при этом лаконичный. И тут случай подвернулся.
Разбирался с особенностями DST/GMT-смещений в разных источниках котировок и календаря. Там многое завязано на первом/втором/последнем воскресенье месяца. Поэтому ядром подобных вычислений является расчет времени начала месяца. Вот эту функцию и попробуем ускорить.
datetime GetMonthTime( const int Year, const int Month ) { const MqlDateTime time = {Year, Month, 1}; return(StructToTime(time)); }
Казалось бы, что тут ускорять? А главное - как?!
Оптимизация - кто кому служит?
Чем меньше математических действий, тем быстрее работает алгоритм. Поэтому немного включив интуицию, напишем общий вид функции, который хотим получить.
#define DAY (24 * 3600) datetime GetMonthTime2( const int Year, const int Month ) { // Количество дней от начала года до начала месяца: январь - 0, февраль - 31, март - 59, ... static const double Months[] = {0, 0, 31, 59, 90, 120, 151, 181, 212 ,243, 273, 304, 334}; return((datetime)(((Year - 1970) * inKoef1 + Months[Month] * inKoef2) * DAY) / DAY * DAY); }
Код родился из следующих соображений. Раз есть год и месяц на входе, то почему бы не ограничиться по одному коэффициенту на каждый входной.
Коэффициенты.
А вот подобрать эти коэффициенты способна стандартная оптимизация. Поэтому пишем ФФ (фитнесс функцию) и натравливаем оптимизатор.
input double inKoef1 = 365; input double inKoef2 = 1; sinput int inYearFrom = 1970; sinput int inYearTo = 2099; input int inMonth = 1; double OnTester() { double Sum = 0; for (int i = inYearFrom; i <= inYearTo; i++) Sum -= (double)MathAbs(GetMonthTime(i, inMonth) - GetMonthTime2(i, inMonth)); return(Sum); }
Для наглядности, в качестве оптимизатора выступит многоядерный MT5-Тестер в режиме математических вычислений.
Запускаем и мгновенно получаем результат.
Нулевая ошибка (полное совпадение с тем, что надо получить) и комбинации соответствующих коэффициентов.
Делаем так для каждого месяца. И в итоге получаем искомую функцию.
// Работает до конца XXI-века. datetime GetMonthTime3( const int Year, const int Month ) { static const double Months[] = {0, 0.45, 31 * 1.01, 59 * 1.01, 90 * 1.007, 120 * 1.005, 151 * 1.004, 181 * 1.004, 212 * 1.003, 243 * 1.003, 273 * 1.002, 304 * 1.002, 334 * 1.002}; return((datetime)(((Year - 1970) * 365.25 + Months[Month]) * DAY) / DAY * DAY); }
Ускорение.
Выглядит некрасиво, но работает в 10-20 раз быстрее исходной!
Наверное, подобная по скорости функция где-то опубликована. Но сгодилась в качестве примера механизма ускорения.
Ссылка на блог автора.