Здравствуйте,
вопрос к разработчикам с большим опытом или к разработчикам.
При оптимизации советников большое значение имеет скорость работы функций.
1) Какие переменные лучше использовать в них, глобальные или локальные?
2) Читал по языку Си, что локальные переменные хранятся в регистрах процессора, следовательно работа с ними быстрее. Так ли это в Metаtrader 4 и 5?
3) Понятно, что без глобальных переменных не обойтись, например в функции глобальная переменная используется 10 раз (арифм. операции, сравнение и т.п.). Лучше ли будет скопировать 1 раз ее в локальную, и далее 10 раз воспользоваться уже локальной переменной?
4) Еще не ясно, с массивами, где-то читал, что они очень медленные в работе. Так ли это?
2. Спецификация языка Си не определяет положение локальных переменных в регистрах. Тем более регистров процессора все равно на все переменные не хватит. В Си есть ключевое слово 'register', но и оно не подразумевает, что переменная должна разместиться в одном из регистров процессора. Это слово просто дает компилятору указание, что необходимо попытаться прооптимизировать работу с ней особенно тчательно.
4. Нет, не так. Массивы предоставляют самый быстрый способ работы с группированными данными. К каждому элементу можно обратиться напрямую, используя его индекс (адресную арифметику по сути). Но у массивов есть существенный недостаток: операции по вставке/изменению размера очень, очень ресурсоемки. Так, если вы накапливаете данные в массив и знаете, что в конце работы программы величина этих данных не превысит 1 000 000 элементов, то лучше сразу выделить все необходимую память, чем поэлементно вставлять новые значения в массив. Такая поэлементная вставка будет раз за разом переразмечать емкость массива, что снизит производительность на порядок. Этот тип данных представлен в стандартной библиотеки классами CArray
Если в процессе работы вам нужно постоянно вставлять новые элементы в массив, или конечный размер массива не известен в принципе, то лучше воспользоваться двухсвязанным списком. Переход между элементами такого списка значительно медленнее чем перебор массива (переход по указателям медленнее адресной арифметики), зато вставка и удаление каждого элемента невероятно быстра. Еще одни минусом связанного списка является то, что обратиться к элементу можно только пройдя предыдущие элементы. Поэтому прямое обращение к элементу крайне накладна. Этот тип данных представлен в стандартной библиотеки классом CList.
Есть еще один тип организации данных: словарь или хеш. Он представляет из себя некое хранилище данных, к каждому элементу которого можно обратиться указав вместо индекса сам объект к которому требуется доступ. Например Hash["Коля","Петя","Вася","Саша","Катя"]; sting my_name = Hash["Вася"]; Hash очень быстро найден значение "Вася" и вернет его переменной my_name. Его организация напоминает что-то среднее между списком и массивом, а по производительности он скорее близок к массивам, хотя и уступает им в скорости. К сожалению в стандартной библиотеке этот тип данных не представлен.
Основных видов памяти в компьютере два: это Стек и Куча. Стек считается более быстрым чем куча. В нем размещаются локальные переменные. В куче размещаются динамические объекты. В целом очень многое зависит от языка программирования. Как сделано конкретно в MQL5 могут ответить только разработчики. В C# например, в стеке размещаются значимые типы: int, double, byte, struct... а в куче ссылочные, т.е. все объекты типа class. В С++ такого жесткого разделения нет. Где и как будет размещаться объект определяет компилятор.
По сабжу: как разработчик Вы должны оптимизировать приложение в зависимости от его задачи. Так например, если Вы активно формируете некоторый массив данных, вставляете и сортируете элементы внутри него, то Вы должны сознательно выбрать в качестве хранилища данных более медленный CList, потому что применительно к Вашей задаче он будет гораздо более эффективней чем более быстрый CArray и т.д.
В общем суть эффективного программирования заключается в том, что бы знать где какой алгоритм использовать, а не в том, что бы переложить работу компилятора на себя.
Есть еще один тип организации данных: словарь или хеш. Он представляет из себя некое хранилище данных, к каждому элементу которого можно обратиться указав вместо индекса сам объект к которому требуется доступ. Например Hash["Коля","Петя","Вася","Саша","Катя"]; sting my_name = Hash["Вася"]; Hash очень быстро найден значение "Вася" и вернет его переменной my_name. Его организация напоминает что-то среднее между списком и массивом, а по производительности он скорее близок к массивам, хотя и уступает им в скорости. К сожалению в стандартной библиотеке этот тип данных не представлен.
Чуть подправлю: словарь (как я понимаю в данном случае это ассоциативный массив) это скорее абстракция / интерфейс для работы с таким типом данных. Хеш (как я понимаю в данном случае это хеш-таблица) это уже реализация/имплементация этой структуры данных, в основе которой работа хеш-функцией. По большому счету ассоциативный массив можно реализовать и через другие структуры данных. Просто реализация через хеш-таблицу в большинстве случаев оптимальна по времени по многим операциям.
Действительно очень странно что в стандартной библиотеке этого нет. A перечисления (enumeration) есть?
- ru.wikipedia.org
Сначала нормальный код, а потом профайлером по нему.
Есть еще один тип организации данных: словарь или хеш. Он представляет из себя некое хранилище данных, к каждому элементу которого можно обратиться указав вместо индекса сам объект к которому требуется доступ. Например Hash["Коля","Петя","Вася","Саша","Катя"]; sting my_name = Hash["Вася"]; Hash очень быстро найден значение "Вася" и вернет его переменной my_name. Его организация напоминает что-то среднее между списком и массивом, а по производительности он скорее близок к массивам, хотя и уступает им в скорости. К сожалению в стандартной библиотеке этот тип данных не представлен.
Не ну вот зачем писать то в чем я так понимаю ниже планки нуля? Словарь и хеш-карта это две абсолютно разных сущности. В С++ есть map и hashmap.
В подавляющем большинстве случаев хватает мапы, которая реализована r-b деревом.
Я не умничаю чрезмерно, я другим не даю этого делать.
В подавляющем большинстве случаев хватает мапы, которая реализована r-b деревом.
Я не умничаю чрезмерно, я другим не даю этого делать.
Да нет, умничаешь и зафлуживаешь ветку здесь ты. Реализаций словаря может быть несколько. Но я написал только о той, что известна лично мне. Я не работаю с С++ и не знаю что такое "мапы", но знаю что в C# стандартный Dictionary реализован на основе хеш-таблицы поэтому мое сравнение с хештаблицей предельно корректно. Словарь в .Net содержит пару "ключ - значение", где уникальность ключа гарантирует хеш функция. Хеш таблица содержит только уникальные объекты, уникальность которых гарантируется той же хеш функцией. Сама хеш функция в развитых средах может быть переопределена наследником. Так в C# поведение хеш функции различно в зависимости от того, имеем ли мы дело с ссылочным или значимым типом...
В общем "умничать" можно до бесконечности, но прежде чем спорить почитай что умные люди пишут о внутренней реализации словаря: Под капотом у Dictionary и ConcurrentDictionary. Кстати данный материал будет весьма интересен всем кто интересуется работой хеш алгоритмов и словарей.
- habrahabr.ru
Перечитал, приношу извинения. У меня таки выражение стандартная библиотека никак не ассоциируется со здешней стандартной. Автоматом подумал на STL отсюда и непонятки.
А шарповский dictionary как раз на hashmap и сделан. И если пишешь про dictionary, то и пиши про него и c#, а не про словарь и вообще.
- www.mql5.com
Перечитал, приношу извинения. У меня таки выражение стандартная библиотека никак не ассоциируется со здешней стандартной. Автоматом подумал на STL отсюда и непонятки.
А шарповский dictionary как раз на hashmap и сделан. И если пишешь про dictionary, то и пиши про него и c#, а не про словарь и вообще.
Как всегда, разность контекста. Ладно проехали)
Вот лучше приведу довольно инетерсный пример на понимание взаимосвязи между хешами, тождествами объектов и коллекций, использующие эти алгоритмы:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //Ассциируем с каждой личностью ее рейтинг на MQL5: Dictionary<CPerson, int> DictionaryRaiting = new Dictionary<CPerson, int>(); DictionaryRaiting.Add(new CPerson("Вася"), 1910); //А теперь побезобразничаем и создадим копии личности: DictionaryRaiting.Add(new CPerson("Вася"), 1910); DictionaryRaiting.Add(new CPerson("Вася"), 1910); DictionaryRaiting.Add(new CPerson("Вася"), 1910); DictionaryRaiting.Add(new CPerson("Вася"), 1910); DictionaryRaiting.Add(new CPerson("Вася"), 1910); DictionaryRaiting.Add(new CPerson("Вася"), 1910); foreach (var person in DictionaryRaiting) Console.WriteLine("Личность: {0}; Оценка:{1}", person.Key.Name, person.Value); Console.ReadKey(); //??? - Как же так? Словарь позволяет хранить одинаковые элементы? Ужасть!!!! //Попробуем еще раз, на этот раз с SPerson - полной копией CPerson но только... Dictionary<SPerson, int> DictionaryRaiting2 = new Dictionary<SPerson, int>(); DictionaryRaiting2.Add(new SPerson("TheExpert"), 7243); //Наученный опытом созданим коллекцию одинаковых SPerson по аналогии с CPerson: DictionaryRaiting2.Add(new SPerson("TheExpert"), 7243); //.... // Crashed!!!!!!! } } /// <summary> /// Личность /// </summary> class CPerson { public CPerson(string name) { mName = name; } public string Name { get { return mName; } } /// <summary> /// Внутреннее имя человека. /// </summary> private string mName; } /// <summary> /// Еще одна личность, (найди 10 отличий от CPerson)))) /// </summary> struct SPerson { public SPerson(string name) { mName = name; } public string Name { get { return mName; } } /// <summary> /// Внутреннее имя человека. /// </summary> private string mName; } }
Этот пример благополучно выполниться до метки Crashed явно указывая нам, что два и более абсолютно одинаковых объекта (конкретно "Вася с рейтингом 1710") могут благополучно находиться в словаре, где по идеи каждый ключ должен быть уникальным. В то же время при попытке загнать объект "TheExpert с рейтингом 7243" уже при второй попытке приведут к исключению времени исполнения. В чем же дело?
А дело здесь в том, что словарь как и хеш таблица использует для идентификации объекта функцию GetHeshCode(). В первом случае эта функция не переопределяется и наследуется от базового объекта Object всех классов как есть. Если хеши не равны, то объекты разные и могут существовать в одной уникальной коллекции. Но дело в том что сама хеш функция использует понятие равенства объектов. А по умолчанию ссылочные объекты считается равными, если ссылаются на один и тот же кусок памяти, а этого-то и нет в данном примере! Ведь каждый раз когда мы создаем объект CPerson оператором new, он создается в новом сегменте памяти, а значит все-таки это разные объекты!
Совсем по-другому дело обстоит со структурами. В Net все значимые типы, такие как структуры размещаются в стеке, а в нем понятие указателя не имеет смысла, там действует другой принцип: последний вошел, первый вышел. Так или иначе для всех структур, переопределен метод Equals(), который считает объекты равными, если они в байт в байт равны между собой. По этому уже при второй попытки запихнуть второй одинаковый объект SPerson в словарь произойдет исключение времени выполнения.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Здравствуйте,
вопрос к разработчикам самого Metаtrader или разработчикам советников с большим опытом.
При оптимизации советников большое значение имеет скорость работы функций.
1) Какие переменные лучше использовать в них, глобальные или локальные?
2) Читал по языку Си, что локальные переменные хранятся в регистрах процессора, следовательно работа с ними быстрее. Так ли это в Metаtrader 4 и 5?
3) Понятно, что без глобальных переменных не обойтись, например в функции глобальная переменная используется 10 раз (арифм. операции, сравнение и т.п.). Лучше ли будет скопировать 1 раз ее в локальную, и далее 10 раз воспользоваться уже локальной переменной?
4) Еще не ясно, с массивами, где-то читал, что работа с ними медленнее, чем с несколькими переменными. Так ли это?
5) константы глобального уровня и переменные глобального уровня, равны по скорости?
------ Полученные ответы из обсуждения ---------------
1) глобальные быстрее (оказывают заметное влияние, если количество операций с ними - несколько тысяч. Если единицы, как в большинстве советников, то влияние - ничтожное.)
3) нет
4) если массив динамический и приходится постоянно пополнять его, то его переразмер занимает много времени. Лучше использовать массивы с заранее определенным размером.