<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=422585&amp;view=findpost&amp;p=3851277</guid>
        <pubDate>Tue, 24 Aug 2021 22:02:16 +0000</pubDate>
        <title>gcc как определить и выделить максимальный непрерывный блок динамической памяти?</title>
        <link>https://forum.sources.ru/index.php?showtopic=422585&amp;view=findpost&amp;p=3851277</link>
        <description><![CDATA[Qraizer: Результаты на 64-х битах в сходных условиях: 16Гб на i5 с одним нагруженным тем же тяжёлым скриптом ядром:<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">Allocated 22906492243 bytes</div><div class="code_line">Residented 11453246118 bytes</div><div class="code_line">Locked 7635497391 bytes</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">Allocated 17179869181 bytes</div><div class="code_line">Residented 1610612733 bytes</div><div class="code_line">Locked 1073741819 bytes</div></ol></div></div></div></div>Первый экземпляр запускался, как и следовало ожидать, очень тяжело, на цикле VirtualLock() до бряка я успел сходить покурить. Второй экземпляр запустился и дошёл до бряка быстро, за пару секунд. После полуминуты в таком состоянии свопы прекратились, фоновый скрипт нормально работал, система потихонечку отходила от перенапряга, физическая память в итоге оказалась утилизирована на 88%.<br>
<br>
P.S. На момент запуска первого экземпляра память была утилизирована на 42%, так что можно было ожидать ~9Гб залоченной памяти, но система оказалась умней.]]></description>
        <author>Qraizer</author>
        <category>C/C++: Системное программирование и WinAPI</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=422585&amp;view=findpost&amp;p=3851273</guid>
        <pubDate>Tue, 24 Aug 2021 18:10:47 +0000</pubDate>
        <title>gcc как определить и выделить максимальный непрерывный блок динамической памяти?</title>
        <link>https://forum.sources.ru/index.php?showtopic=422585&amp;view=findpost&amp;p=3851273</link>
        <description><![CDATA[Qraizer: Строго говоря, дело тут не в Windows или Linux, дело в разрядности приложения. В 64-биной винде будет то же самое.<br>
Задача, в общем-то неоднозначная. Предположим, ты определил эффективный для тебя размер региона памяти. Ок, тебя ОСь свопить не будет... но ведь в системе есть и другие процессы, и оставив им очень мало памяти, ты заставишь ОСь свопать их, и они, получая управление даже изредка, всё равно будут деградировать производительность системы в целом, а значит и твою тоже. Готовых рецептов тут просто не может быть, т.к. золотая середина завист от факторов, которые достоверно просчитать в общем случае просто невозможно. <br>
<br>
<span class="tag-color tag-color-named" data-value="mergepost" style="color: mergepost"><span class='tag-size' data-value='7' style='font-size:7pt;'>Добавлено <time class="tag-mergetime" datetime="2021-08-24T18:31:36+00:00">24.08.21, 18:31</time></span></span><br>
Я бы предложил сначала просто получить регион максимального размера, в WinAPI это VirtualAlloc(). Так ты получишь потенциально самый большой размер региона, который только возможно, но в 64-х битах наверняка сповиться он будет безбожно. Затем попробовать поколдовать над размерами рабочего пространства посредством SetProcessWorkingSetSize(). Так ты сможешь получить эффективный размер региона, который система может позволить тебе оставлять резидентным в памяти, хотя и без гарантии этой резидентности и ценой деградации производительности системы в целом. И наконец залочить регион в памяти с помощью VirtualLock(). Так ты получишь максимально большой, но всё ещё разумный по размеру регион памяти, который не будет свопаться. После этого можно VirtualFree() декоммитить &quot;лишние&quot; страницы, отдав т.о. избыточно отхапанную память на другие нужды и ... посмотреть, что из этого алгоритма получилось. Что и как из этого будет применимо в Linux, без понятия. <br>
<br>
<span class="tag-color tag-color-named" data-value="mergepost" style="color: mergepost"><span class='tag-size' data-value='7' style='font-size:7pt;'>Добавлено <time class="tag-mergetime" datetime="2021-08-24T18:32:52+00:00">24.08.21, 18:32</time></span></span><br>
Естественно, подбор этих максимумов надо делать разумно, например, дихотомией. <br>
<br>
<span class="tag-color tag-color-named" data-value="mergepost" style="color: mergepost"><span class='tag-size' data-value='7' style='font-size:7pt;'>Добавлено <time class="tag-mergetime" datetime="2021-08-24T18:42:30+00:00">24.08.21, 18:42</time></span></span><br>
P.S. Я тут по быстрому накидал нечто вот такое (внимание&#33; синтетика&#33; в продакшне как есть не использовать&#33;):<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">#define NOMINMAX</div><div class="code_line">#include &#60;windows.h&#62;</div><div class="code_line">#include &#60;iostream&#62;</div><div class="code_line">#include &#60;limits&#62;</div><div class="code_line">&nbsp;</div><div class="code_line">int main()</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp;size_t size &nbsp; &nbsp;= std::numeric_limits&#60;decltype(size)&#62;::max(),</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; oldSize = size;</div><div class="code_line">&nbsp;&nbsp;void &nbsp;*mem;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;do</div><div class="code_line">&nbsp;&nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp;mem = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (mem == NULL)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;oldSize = size;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;size &nbsp;&#62;&#62;= 1;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;continue;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;size_t newSize = (oldSize &#62;&#62; 1) + (size &#62;&#62; 1);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;oldSize = size;</div><div class="code_line">&nbsp;&nbsp; &nbsp;size &nbsp; &nbsp;= newSize;</div><div class="code_line">&nbsp;&nbsp; &nbsp;VirtualFree(mem, 0, MEM_RELEASE);</div><div class="code_line">&nbsp;&nbsp;} while (size != oldSize);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;size_t allocated = size;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;mem = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);</div><div class="code_line">&nbsp;&nbsp;if (mem == NULL)</div><div class="code_line">&nbsp;&nbsp; &nbsp;return std::cout &#60;&#60; &quot;Ops!\n&quot;,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1;</div><div class="code_line">&nbsp;&nbsp;std::cout &#60;&#60; &quot;Allocated &quot; &#60;&#60; size &#60;&#60; &quot; bytes&quot; &#60;&#60; std::endl;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;do</div><div class="code_line">&nbsp;&nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (SetProcessWorkingSetSize(GetCurrentProcess(), size, size) == FALSE)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;oldSize = size;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;size &nbsp;&#62;&#62;= 1;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;continue;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;size_t newSize = (oldSize &#62;&#62; 1) + (size &#62;&#62; 1);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;oldSize = size;</div><div class="code_line">&nbsp;&nbsp; &nbsp;size &nbsp; &nbsp;= newSize;</div><div class="code_line">&nbsp;&nbsp;} while (size != oldSize);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;if (SetProcessWorkingSetSize(GetCurrentProcess(), size, size) == FALSE)</div><div class="code_line">&nbsp;&nbsp; &nbsp;return std::cout &#60;&#60; &quot;Ops 2!\n&quot;,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2;</div><div class="code_line">&nbsp;&nbsp;std::cout &#60;&#60; &quot;Residented &quot; &#60;&#60; size &#60;&#60; &quot; bytes&quot; &#60;&#60; std::endl;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;do</div><div class="code_line">&nbsp;&nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (VirtualLock(mem, size) == FALSE)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;oldSize = size;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;size &nbsp;&#62;&#62;= 1;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;continue;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;size_t newSize = (oldSize &#62;&#62; 1) + (size &#62;&#62; 1);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;oldSize = size;</div><div class="code_line">&nbsp;&nbsp; &nbsp;size &nbsp; &nbsp;= newSize;</div><div class="code_line">&nbsp;&nbsp; &nbsp;VirtualUnlock(mem, oldSize);</div><div class="code_line">&nbsp;&nbsp;} while (size != oldSize);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;if (VirtualLock(mem, size) == FALSE)</div><div class="code_line">&nbsp;&nbsp; &nbsp;return std::cout &#60;&#60; &quot;Ops 3!\n&quot;,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3;</div><div class="code_line">&nbsp;&nbsp;std::cout &#60;&#60; &quot;Locked &quot; &#60;&#60; size &#60;&#60; &quot; bytes&quot; &#60;&#60; std::endl;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;SetProcessWorkingSetSize(GetCurrentProcess(), size, size);</div><div class="code_line">&nbsp;&nbsp;VirtualFree((char*)mem + size, allocated - size, MEM_DECOMMIT);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;std::cout &#60;&#60; &quot;Ok&quot; &#60;&#60; std::endl; &nbsp; &nbsp; &nbsp; // &#60;- тут бряк</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;VirtualUnlock(mem, oldSize);</div><div class="code_line">&nbsp;&nbsp;SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);</div><div class="code_line">&nbsp;&nbsp;VirtualFree(mem, 0, MEM_RELEASE);</div><div class="code_line">}</div></ol></div></div></div></div>и получил под 32-битной 7кой с 4Гб на борту<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">Allocated 1431655763 bytes</div><div class="code_line">Residented 1431655762 bytes</div><div class="code_line">Locked 954437164 bytes</div></ol></div></div></div></div>остановившись под отладчиком в указанном месте и запустил второй процесс вот с такими результатами:<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">Allocated 1431655763 bytes</div><div class="code_line">Residented 477218569 bytes</div><div class="code_line">Locked 318145701 bytes</div><div class="code_line">Ok</div></ol></div></div></div></div>При этом на фоне работал тяжёлый JavaScript-овый алгоритм в браузере, целиком отжирая одно ядро у Core i3. Ну т.е. цифры выглядят разумными, и система вполне жива и не деградирует. Есть вероятность, что эта синтетика вполне может служить примером золотой середины. <br>
<br>
<span class="tag-color tag-color-named" data-value="mergepost" style="color: mergepost"><span class='tag-size' data-value='7' style='font-size:7pt;'>Добавлено <time class="tag-mergetime" datetime="2021-08-24T18:53:43+00:00">24.08.21, 18:53</time></span></span><br>
Естественно, эксперимент не чистый, процесс под анализом стоит и ничего не делает. Ну и буду дома, проверю ещё на 64-х битах с 16Гб.]]></description>
        <author>Qraizer</author>
        <category>C/C++: Системное программирование и WinAPI</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=422585&amp;view=findpost&amp;p=3851249</guid>
        <pubDate>Tue, 24 Aug 2021 04:57:45 +0000</pubDate>
        <title>gcc как определить и выделить максимальный непрерывный блок динамической памяти?</title>
        <link>https://forum.sources.ru/index.php?showtopic=422585&amp;view=findpost&amp;p=3851249</link>
        <description><![CDATA[mkudritsky: Разрабатываю программы решения Задачи Коммивояжера (ЗК) на языке Си в среде Qt. Операционные системы: Linux, Windows.<br>
Особенность ЗК - для решения этой задачи большой размерности (например, 300 городов) часто бывает мало 8-16-32-64Гб RAM.<br>
Особенно нетерпимо - сброс огромных массивов данных, по которым идет расчет, из RAM в SWAP.<br>
<br>
Вот и возникает задача: как определить максимально доступный объем непрерывной динамической памяти?<br>
Поиск в Интернете привел к созданию такого фрагмента кода для достижения указанной цели:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// Операционная система определяется макросом WINVER (есть в Windows и нет в Linux)</div><div class="code_line">#ifndef WINVER</div><div class="code_line">#include &#60;sys/sysinfo.h&#62;</div><div class="code_line">#else</div><div class="code_line">#include &#60;sysinfoapi.h&#62;</div><div class="code_line">#endif</div><div class="code_line">&nbsp;</div><div class="code_line">// Переменные для информации об основных параметрах ОС (главным образом - RAM). Заодно определяется &quot;слэш&quot; в файловой системе</div><div class="code_line">#ifndef WINVER</div><div class="code_line">&nbsp;&nbsp; &nbsp;struct sysinfo osInfo;</div><div class="code_line">&nbsp;&nbsp; &nbsp;char cSl = &#39;/&#39;;</div><div class="code_line">#else</div><div class="code_line">&nbsp;&nbsp; &nbsp;MEMORYSTATUSEX osInfo;</div><div class="code_line">&nbsp;&nbsp; &nbsp;char cSl = &#39;\&#39;;</div><div class="code_line">#endif</div><div class="code_line">&nbsp;</div><div class="code_line">unsigned long long int</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Общий объем доступной непрерывной динамической RAM, шаг при поиске iMemMax</div><div class="code_line">&nbsp;&nbsp; &nbsp;iMemMax, iDMem;</div><div class="code_line">char</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Указатель, &quot;нарезающий&quot; выделяемую память для массивов данных, используемых при решении ЗК </div><div class="code_line">&nbsp;&nbsp; &nbsp;*pByte; </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;</div><div class="code_line">// Чтение информации о состоянии операционной системы</div><div class="code_line">#ifndef WINVER</div><div class="code_line">&nbsp;&nbsp; &nbsp; sysinfo(&amp;osInfo);</div><div class="code_line">&nbsp;&nbsp; &nbsp; iMemMax = osInfo.freeram;</div><div class="code_line">&nbsp;&nbsp; &nbsp; // &quot;Ефрейторский&quot; зазор - настолько пошагово уменьшается память, если ее нельзя выделить</div><div class="code_line">&nbsp;&nbsp; &nbsp; iDMem &nbsp; = osInfo.totalram / 1000 + 1; </div><div class="code_line">#else</div><div class="code_line">&nbsp;&nbsp; &nbsp; osInfo.dwLength = sizeof(osInfo);</div><div class="code_line">&nbsp;&nbsp; &nbsp; if (!GlobalMemoryStatusEx(&amp;osInfo)) { // osInfo.freeram;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;Не могу определить размер динамической памяти!&quot;);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return -1;</div><div class="code_line">&nbsp;&nbsp; &nbsp; }</div><div class="code_line">&nbsp;&nbsp; &nbsp; iMemMax = osInfo.ullAvailPhys;</div><div class="code_line">&nbsp;&nbsp; &nbsp; iDMem &nbsp; = osInfo.ullTotalPhys / 1000 + 1;</div><div class="code_line">#endif</div><div class="code_line">&nbsp;&nbsp; &nbsp; pByte = (char *)calloc(iMemMax, sizeof(char));</div><div class="code_line">&nbsp;&nbsp; &nbsp; while (!pByte &amp;&amp; (iMemMax &#62; iDMem)) {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; iMemMax -= iDMem;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; pByte = (char *)calloc(iMemMax, sizeof(char));</div><div class="code_line">&nbsp;&nbsp; &nbsp; }</div><div class="code_line">&nbsp;&nbsp; &nbsp; if (!pByte) {</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;Не могу выделить динамическую память!\n&quot;);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return -1;</div><div class="code_line">&nbsp;&nbsp; &nbsp; }</div><div class="code_line">#ifndef WINVER</div><div class="code_line">&nbsp;&nbsp; &nbsp; printf(&quot;Динамической памяти &quot;); printf(&quot;RAM = %lld Mbyte\n&quot;, &nbsp;iMemMax / 1048576); &nbsp;// 1048576 &nbsp; = 1024 *1024</div><div class="code_line">#else</div><div class="code_line">&nbsp;&nbsp; &nbsp; printf(&quot;Динамической памяти &quot;); printf(&quot;RAM = %I64d Mbyte\n&quot;, iMemMax / 1048576); // 1048576 &nbsp; = 1024 *1024</div><div class="code_line">#endif</div></ol></div></div></div></div><br>
<br>
В чем состоит проблема?<br>
Как это ни странно, в Windows-7 32bit проблем нет: программа в Qt (компиляция realese) выделяет 1600Мб RAM, а в mingw32 (ключ -O3) выделяет 1860Мб RAM.<br>
<br>
Все проблемы с Linux.<br>
Когда многократно запускаешь скомпилированную программу, сначала идет все хорошо (пусть будет 8Гб физической RAM):<br>
например, при первом запуске выделяется блок в 7000Мб RAM;<br>
при втором запуске (пример) выделяется уже 7200Мб RAM;<br>
и так далее - при каждом следующем запуске ОС освобождает все больше RAM для решения Задачи Коммивояжера.<br>
<br>
Заканчивается все тем, что из 8192Мб физической RAM выделяется, скажем, 7860Мб RAM и при этом часть памяти начинает сидеть в SWAP&#33;<br>
То есть начинает использоваться SWAP на HDD&#33;<br>
Визуально это наблюдается так: HDD начинает перманентно &quot;трещать&quot;. Трещит и 5 минут, и 10 минут, и 20 минут...<br>
Мне приходится делать вот что: начиная с некоторого момента перед запуском программы решения ЗК приходится запускать LibreOffice только с одной целью - чтобы офис частично занял RAM (после запуска ЗК я Офис закрываю).<br>
<br>
Вопрос, собственно, такой: как в Linux сделать так, чтобы выделяемый блок памяти (близкий к максимальному) сидел четко в RAM?<br>
Может мой код надо как-то подрегулировать? (Замечания и предложения, разумеется, принимаются).]]></description>
        <author>mkudritsky</author>
        <category>C/C++: Системное программирование и WinAPI</category>
      </item>
	
      </channel>
      </rss>
	