Почему меняется скорость выполнения математических операций на C++?
Есть двумерный (также и с трехмерным) динамический массив. В него загружаются данные и потом он используется. Данные весят несколько ГБ. С массивом производятся простые математические операции - сложения, умножения, корень и похожее. (Результат в массив не сохраняется. То есть массив постоянен.) Все происходит на Intel Xeon E5-2660 v4 в 10 потоках. (Сам процессор 14 ядер). Вопрос почему один раз одни и те же операции идут - 0.1 сек. В другой раз (если ничего не делать минуты 2) - 1 сек. Почему так происходит? Может надо что-то изменить в настройках Visual Studio 2015 Release? Или в настройках сервера? OC - Windows Server 2012 R2.
P.S. Никакие другие операции не тормозят. Именно математические. Или обращение к массиву (такое может быть)?
P.P.S. Еще заметил что когда нормально (за 0.1 сек) выполняются операции - процессор нагружается на 10-15%. Когда за 1 сек - больше 40%.
Другие операции на сервере не выполняются. Так что процессор по-максиму свободен. ОЗУ тоже свободно достаточно (несколько ГБ).
igorsap13 , поясни вот что.
Двухмерный или трехмерный массив - эт хорошо. Как он представлен в памяти? Непрерывным блоком или набором фрагментированных блоков?
Покажи наглядно, в каких позициях этого массива могут выполняться одновременные операции из разных потоков?
Меня интересуют фактические индексы ячеек.
Еще интересно узнать, элементы какого типа находятся в этом размере. Если это нестандартный и неплоский тип, то интереснее всего размер ячейки этого массива.
Евгений Шатунов, массив состоит из float (float ***array).
Непрерывным блоком или набором фрагментированных блоков? Честно я не знаю, объявлял так - (new float**[m_index_max]; потом new float*[a]; потом new float[110];) Насчет позиций - они точно не пересекаются, потому что потоки делят массив на 10 частей и каждый поток работает со своей частью. А так позиций - с начала и до конца каждой части.
Денис Загаевский, элементов же столько же останется. Почему тогда будет меньше кешов? Указатели в C++ кешируются? Если их не использовать некоторое время, то они чистятся?
igorsap13 , в общем и целом у тебя есть несколько проблем. Первая - это, как Дениска заметил, промахи по предсказанию востребованных данных. Вторая проблема - это или наличие т.н. false sharing, или отсутствие т.н. true sharing. Третья проблема - в явной фрагментированности данных.
Все эти проблемы взаимосвязаны и их, на самом деле, можно сократить до одной: у тебя просто проблемы с кешированием данных в процессоре.
В остальном, ты не предоставляешь реальные данные, поэтому нормальный ответ лично я написать не могу.
P.S. Никакие другие операции не тормозят. Именно математические. Или обращение к массиву (такое может быть)?
А как ты определяешь, что именно математические?
Если твой код не зависит от каких-то случайных значений, то скорее всего проблема в занятости ОС, она банально выполняет другие задачи и не даёт твоей много процессорного времени. Как вариант решения - поставить максимальный приоритет твоему процессу.
Но это только догадки, для точного ответа нужно больше информации
devalone, Еще заметил что когда нормально (за 0.1 сек) выполняются операции - процессор нагружается на 10-15%. Когда за 1 сек - больше 40%.
Другие операции на сервере не выполняются. Так что процессор по-максиму свободен. ОЗУ тоже свободно достаточно (несколько ГБ).
igorsap13, потому что когда ты берешь память по некоторому адресу, в кеш попадает не только 4-8 байт, которые ты берешь, но и сколько-то килобайт вокруг. Кеш не бесконечный, поэтому когда ты много скачешь по памяти (а именно это ты делаешь, ходя по такому фрагметированному массиву), какие-то данные постоянно выгружаются туда-обратно. Это так, на пальцах, в реале всё сложнее.
Денис Загаевский, переделал в одномерный float *a = new float[5 000 000 000]; (размер - unsigned long long)
Стало работать быстрее, спасибо! Правда все равно падает скорость иногда. Как я понимаю проблема с кэшом процессора. Сколько он нужен для таких данных? Как это рассчитывать? У моего процессора 35Мб. Можете, пожалуйста, скинуть ссылки почитать про то, как настраивать кэш процессора.
Мне все эти данные нужны для операций, они рассчитываются от начала и до конца. Проход делаю в 10 потоках (рассчитываю индекс начала и конца каждой части, массив один - глобальная переменная).
Сейчас массив не фрагментирован, правильно?