<?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=411266&amp;view=findpost&amp;p=3862378</guid>
        <pubDate>Sat, 02 Apr 2022 16:08:03 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3862378</link>
        <description><![CDATA[mkudritsky: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=411266&view=findpost&p=3862370'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Majestio &#064; <time class="tag-quote__quoted-time" datetime="2022-04-02T12:36:55+03:00">02.04.22, 09:36</time></span><div class='quote '>Неужели при сборке нельзя определить для какой платформы собирается билд?</div></div><br>
<br>
Кстати, вопрос открытый&#33;<br>
(Сейчас апробирую отличный совет выше).<br>
<br>
Как из программы на Си/C++ определить - в какой ОС ее пытаются скомпилировать?<br>
Если компилировать в Qt, то тут все относительно просто: в Windows есть макрос WINVER, а в Linux его, разумеется, нет.<br>
Но, увы, Qt не всегда спасает. Например, я не знаю, как установить 64bit Qt под Windows.<br>
По этой причине я, например, в Win 7 64bit программы отлаживаю в Qt 32bit и уже отлаженную программу в командной строке компилирую в mingw64 уже под 64bit Windows.<br>
(Дело в том, что в компиляторе mingw64 нет встроенного макроса WINWER и его приходиться указывать явно в командной строке).<br>
<br>
А так было бы неплохо в самой программе узнавать, в какой ОС и какой разрядности ее пытаются скомпилировать, - можно было бы избавиться от многих строк условной компиляции.<br>
<br>
P.S. Что касается cSl, то я забыл удалить этот комментарий, который сделал лет 5 назад, когда был в Си еще совсем зеленым.<br>
Слэш нужен для того, чтобы выводить данные в файлы, расположенные в разных директориях. А слэш, как известно, в Win и в Linux разный. Спасибо Билли Гейтсу.]]></description>
        <author>mkudritsky</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3862370</guid>
        <pubDate>Sat, 02 Apr 2022 09:36:55 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3862370</link>
        <description><![CDATA[Majestio: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=411266&view=findpost&p=3862359'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>mkudritsky &#064; <time class="tag-quote__quoted-time" datetime="2022-04-02T04:53:51+00:00">02.04.22, 04:53</time></span><div class='quote '>char cSl = &#39;/&#39;;            // По переменной cSl далее в программе определяется, где мы находимся (Linux, Windows)</div></div><br>
Просто дичь&#33; Неужели при сборке нельзя определить для какой платформы собирается билд?<br>
<a class='tag-url' href='https://majestio.info/viewtopic.php?id=78' target='_blank'>Что может быть проще?</a>]]></description>
        <author>Majestio</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3862359</guid>
        <pubDate>Sat, 02 Apr 2022 04:53:51 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3862359</link>
        <description><![CDATA[mkudritsky: Оживлю давнишнюю свою тему&#33;<br>
Чтобы не читать все выше, изложу суть проблемы - надо выделить оперативную память в максимальных количествах для решения некоторых труднорешаемых комбинаторных задач.<br>
Но при этом надо, чтобы эта память не выравнивалась по словам (32bit), а заполнялась полезными данными подряд, &quot;плечом к плечу&quot;, без &quot;дырок&quot; и &quot;проплешин&quot; на выравнивание данных.<br>
Да, при этом время расчетов возрастает на 30-40%, но зато абсолютно вся память используется&#33;<br>
<br>
Сейчас я этой цели достигаю следующим образом.<br>
Текст фрагмента программы (кстати, для Linux и для Windows) приведен с подробными комментариями:<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">#ifndef WINVER</div><div class="code_line">#include &#60;sys/sysinfo.h&#62; &nbsp; &nbsp;// Linux</div><div class="code_line">#else</div><div class="code_line">#include &#60;sysinfoapi.h&#62; &nbsp; &nbsp; // Windows</div><div class="code_line">#endif</div><div class="code_line">&nbsp;</div><div class="code_line">// Информация об основных параметрах ОС (главным образом - RAM)</div><div class="code_line">#ifndef WINVER</div><div class="code_line">struct sysinfo osInfo;</div><div class="code_line">char cSl = &#39;/&#39;; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// По переменной cSl далее в программе определяется, где мы находимся (Linux, Windows)</div><div class="code_line">#else</div><div class="code_line">MEMORYSTATUSEX osInfo;</div><div class="code_line">char cSl = &#39;\&#39;;</div><div class="code_line">#endif</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Переключение локали для вывода кирилицы в терминальном окне</div><div class="code_line">&nbsp;&nbsp; &nbsp;setlocale(LC_CTYPE, &quot;&quot;);</div><div class="code_line">&nbsp;</div><div class="code_line">unsigned long long int</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Масимальный объем выделенной динамической памяти, смещение относительно начального адреса, вспомогательная переменная</div><div class="code_line">&nbsp;&nbsp; &nbsp;iMemMax, iMem, iDMem;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; // Начальное значение смещения относительно начального адреса</div><div class="code_line">&nbsp;&nbsp; &nbsp; iMem = 0;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; // Чтение информации о состоянии операционной системы</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 - (osInfo.freeram / 100) * 4; // 4% от свободной памяти</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; PrintCons(&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">&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;</div><div class="code_line">&nbsp;&nbsp; &nbsp; // Выделение максимально возможного объема динамической памяти RAM</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; PrintCons(&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;Динамической памяти RAM = &quot;); printf(&quot;%lld Mbyte\n&quot;, iMemMax / 1048576); &nbsp;// 1048576 &nbsp; = 1024 *1024</div><div class="code_line">#else</div><div class="code_line">&nbsp;&nbsp; &nbsp; printf(&quot;Динамической памяти RAM = &quot;); printf(&quot;%I64d Mbyte\n&quot;, iMemMax / 1048576); // 1048576 &nbsp; = 1024 *1024</div><div class="code_line">#endif</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Пример работы с динамической памятью (&quot;нарезание&quot; кусков памяти относительно pByte в пределах iMemMax</div><div class="code_line">&nbsp;&nbsp; &nbsp;int *Ivar, *Iopt; // Массивы с последовательностями индексов городов (текущий и оптимальный) при решении Задачи Коммивояжера</div><div class="code_line">&nbsp;&nbsp; &nbsp;int Ng = 300; &nbsp; &nbsp; // Число городов в Задаче Коммивояжера; может вводиться из консоли</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; // Массив размером Ng для хранения промежуточных маршрутов</div><div class="code_line">&nbsp;&nbsp; &nbsp; Ivar = (int *)(pByte + iMem); // calloc(Ng, sizeof(int));</div><div class="code_line">&nbsp;&nbsp; &nbsp; iMem += Ng * sizeof(int);</div><div class="code_line">&nbsp;&nbsp; &nbsp; if (iMem &#62; iMemMax)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; {printf(&quot;Не могу выделить память!\n&quot;); free(pByte); return -1;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; // Массив для хранения оптимального маршрута</div><div class="code_line">&nbsp;&nbsp; &nbsp; Iopt = (int *)(pByte + iMem); // calloc(Ng, sizeof(int));</div><div class="code_line">&nbsp;&nbsp; &nbsp; iMem += Ng * sizeof(int);</div><div class="code_line">&nbsp;&nbsp; &nbsp; if (iMem &#62; iMemMax)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; {printf(&quot;Не могу выделить память!\n&quot;); free(pByte); return -1;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; // Ну и так далее. Идея, наверное, понятна!</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; // Освобождается выделенная динамическая память одним элегантным движением:</div><div class="code_line">&nbsp;&nbsp; &nbsp; free(pByte);</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
Кстати, смещением iMem (как в примере выше) очень удобно управлять динамической памятью, если запросы к ней меняются, скажем, в теле какого-нибудь цикла.<br>
Например, в теле цикла часть динамически выделенных данных не меняется в плане их структуры (но значения данных, конечно, меняются&#33;), а часть данных вообще меняет структуру кардинальным образом&#33;<br>
<br>
Так вот, ту часть данных, которая не меняет структуру, располагаем сразу за началом глобального массива pByte и запоминаем смещение:<br>
iMemCONST = iMem;<br>
Ну а те данные, которые динамически меняют структуру в процессе счета (цикла) располагаем за смещением iMemCONST, периодически возвращаясь к этому смещению для выстраивания от него новой, измененной, структуры данных.<br>
Очень удобно&#33; Я даже не знаю, как это сделать просто и безошибочно только лишь при помощи malloc/calloc и free...]]></description>
        <author>mkudritsky</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3739353</guid>
        <pubDate>Sat, 09 Sep 2017 04:23:33 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3739353</link>
        <description><![CDATA[Qraizer: Вполне себе контролируемый. И всегда был таким. В линейке NT, правда, для этого нужны права админа.]]></description>
        <author>Qraizer</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3739352</guid>
        <pubDate>Sat, 09 Sep 2017 00:56:43 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3739352</link>
        <description><![CDATA[mkudritsky: Итак, господа, проблема решена&#33;<br>
Все действительно оказалось просто: требуемую память (благо, что ее размер можно вычислить заранее) надо запрашивать сразу, а не по мере выполнения программы.<br>
Ну и после выделения требуемого очень большого фрагмента RAM надо просто расставить по нему указатели требуемым образом.<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">#include &#60;stdlib.h&#62;</div><div class="code_line">#include &#60;stdio.h&#62;</div><div class="code_line">//-------------------------------------</div><div class="code_line">/*</div><div class="code_line">typedef struct {// Структура со свойствами города текущего состояния</div><div class="code_line">&nbsp;char sNg; // Номер города нижележащего состояния, куда оптимально надо идти из текущего состояния. Принадлежит базису текущего состояния!</div><div class="code_line">&nbsp;unsigned short Smin; // Минимальная длина пути коммивояжера в текущее состояние</div><div class="code_line">} sG;</div><div class="code_line">*/</div><div class="code_line">typedef char sG[3]; // Первый байт - номер города текущего состояния; и 2+3 байты - минимальная длина пути коммивояжера в текущее состояние</div><div class="code_line">//-------------------------------------</div><div class="code_line">int &nbsp;Ng, Nc, &nbsp;// Число городов коммивояжера и число базисов состояний (Nc=2**Ng-1)</div><div class="code_line">&nbsp;&nbsp; &nbsp; iSost, &nbsp; // Базис (1-биты) и конечные города состояния (0-биты)</div><div class="code_line">&nbsp;&nbsp; &nbsp; *bNg; &nbsp; &nbsp;// Массив &quot;битов&quot;, соответствующих номерам городов (1-бит номер города, остальные 0-биты)</div><div class="code_line">sG **Ns, &nbsp; &nbsp; &nbsp;// Массив соответсвия &quot;Базис=&#62;Ссылка на его набор sG&quot; (всего Nc)</div><div class="code_line">&nbsp;&nbsp; *Ndat; &nbsp; &nbsp; // Массив элементов sG для каждого состояния (всего их Ng*2**(Ng-1))</div><div class="code_line">unsigned long long int Lsost, &nbsp; // Счетчик размера всей необходимой структуры (в байтах)</div><div class="code_line">&nbsp;&nbsp; &nbsp;Ldat; &nbsp; &nbsp; // Счетчик состояний (структур sG в массиве Ndat)</div><div class="code_line">//-------------------------------------------------------------------------------------------------</div><div class="code_line">&nbsp;</div><div class="code_line">int main(void) {</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// Размер структуры</div><div class="code_line">&nbsp;printf(&quot;Размер структуры sG = %lu\n&quot;, sizeof(sG));</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// Задание числа городов</div><div class="code_line">&nbsp;printf(&quot;Число городов Ng = &quot;);</div><div class="code_line">&nbsp;scanf(&quot;%d&quot;,&amp;Ng);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// Нахождение числа базисов состояний (2**Ng)</div><div class="code_line">&nbsp;Nc=1;</div><div class="code_line">&nbsp;Nc=(Nc&#60;&#60;Ng);</div><div class="code_line">&nbsp;Nc-=1; // Nc=2**Ng-1</div><div class="code_line">&nbsp;printf(&quot;Число базисов состояний Nc = %i\n&quot;, Nc);</div><div class="code_line">&nbsp;//</div><div class="code_line">&nbsp;// Задание вспомогательных массивов данных</div><div class="code_line">&nbsp;bNg=(int*)calloc(Ng,sizeof(int)); &nbsp;// Бит &#60;--&#62; город. Массив малый и его не считаем в Lsost</div><div class="code_line">&nbsp;Ns=(sG**)calloc(Nc,sizeof(sG*)); // Ns содержит ссылки на элементы массива Ndat для каждого базиса</div><div class="code_line">&nbsp;Lsost=Nc*sizeof(sG*); &nbsp; &nbsp; &nbsp;// такую RAM мы уже выделили (массив указателей размером Nc)</div><div class="code_line">&nbsp;printf(&quot;Размер массива базисов состояний = %llu\n&quot;, Lsost);</div><div class="code_line">&nbsp;Ldat=Ng*((1+Nc)&#62;&#62;1); // Число состояний коммивояжера</div><div class="code_line">&nbsp;Ndat=(sG*)calloc(Ldat,sizeof(sG)); // Ng*2**(Ng-1) элементов sG - данные для каждого состояния коммивояжера</div><div class="code_line">&nbsp;if (!Ndat)</div><div class="code_line">&nbsp;&nbsp;{ printf(&quot;Не могу выделить память!\n&quot;); return 1; }</div><div class="code_line">&nbsp;Lsost+=Ldat*sizeof(sG);</div><div class="code_line">&nbsp;printf(&quot;Размер всей структуры данных поиска = %llu\n&quot;, Lsost);</div><div class="code_line">&nbsp;//</div><div class="code_line">&nbsp;// Заполнение битов-городов</div><div class="code_line">&nbsp;bNg[0]=1; // Для i-го города i-й бит в целой переменной типа int равен 1; остальные биты - 0</div><div class="code_line">&nbsp;for (int i=1; i&#60;Ng ; i++)</div><div class="code_line">&nbsp;&nbsp;bNg[i]=bNg[i-1]&#60;&#60;1;</div><div class="code_line">&nbsp;//</div><div class="code_line">&nbsp;// Построение всей структуры графа поиска. Выделение необходимой для расчетов памяти</div><div class="code_line">&nbsp;Ns[0]=Ndat; // sG состояний с нулевым базисом находятся в самом начале массива Ndat</div><div class="code_line">&nbsp;sG* NdatProm=Ndat; // Указатель для перемещения между элементами Ndat</div><div class="code_line">&nbsp;for (iSost=0; iSost&#60;Nc-1; iSost++) {</div><div class="code_line">&nbsp;&nbsp;int j1=0; // Начало вычисления кратности текущего состояния (подсчет ненулевых битов в числе iSost</div><div class="code_line">&nbsp;&nbsp;for (int j=0; j&#60;Ng; j++)</div><div class="code_line">&nbsp;&nbsp; if (iSost &amp; bNg[j]) j1++; // Счетчик увеличивается только на 1-битах</div><div class="code_line">&nbsp;&nbsp;NdatProm+=(Ng-j1);</div><div class="code_line">&nbsp;&nbsp;Ns[iSost+1]=NdatProm; // Выделена память для всех состояний с текущим базисом iSost</div><div class="code_line">&nbsp;}</div><div class="code_line">&nbsp;printf(&quot;Завершение расчетов\n&quot;);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// Освобождение ранее выделенной памяти:</div><div class="code_line">&nbsp;free(bNg); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Освобождение массива битов-городов</div><div class="code_line">&nbsp;free(Ns);</div><div class="code_line">&nbsp;free(Ndat); &nbsp; // Удаление массива состояний (ссылки на структуру для каждого базиса)</div><div class="code_line">&nbsp;</div><div class="code_line">} // Завершение программы main</div></ol></div></div></div></div><br>
<br>
Отличие от предыдущего кода состоит в том, что введен массив Ndat с данными для всех состояний коммивояжера и потом в нем просто расставляются адреса базисов состояний, хранимые в массиве Ns.<br>
Ура&#33; Память я отвоевал&#33; Больше дыр в RAM не образуется и данные для каждого состояния упаковываются &quot;плечом к плечу&quot;.<br>
<br>
Какова же плата за такое расположение данных, которые теперь не выравниваются по степени двойки?<br>
Вот результаты расчетов на машине с 16Гб RAM и процессором Intel Core i7 2600K.<br>
Решается честная разомкнутая Задача Коммивояжера в 64bit архитектуре на одном ядре CPU:<br>
<br>
I. Число городов = 25<br>
Старый метод выделения памяти: Tсчета=134сек; RAM=1949Мб<br>
Новый метод выделения памяти: Tсчета=153сек; RAM=1458Мб<br>
<br>
II. Число городов = 26<br>
Старый метод выделения памяти: Tсчета=294сек; RAM=4000Мб<br>
Новый метод выделения памяти: Tсчета=342сек; RAM=3013Мб<br>
<br>
III. Число городов = 27<br>
Старый метод выделения памяти: Tсчета=660сек; RAM=8208Мб<br>
Новый метод выделения памяти: Tсчета=753сек; RAM=6219Мб<br>
<br>
ВЫВОДЫ:<br>
1. Упаковывание RAM &quot;плечом к плечу&quot; ведет к экономии памяти на примерно 24%, но увеличивает время расчетов примерно на 12-14%.<br>
2. Оказалось, что функция calloc() - НЕ медленная процедура. В более ранних реализациях алгоритма я использовал calloc() для выделения памяти (по три байта) для каждого из миллиардов состояний да еще и в процессе расчетов&#33; И все считалось по старому методу быстро. Кстати, метод new из C++ тоже быстро выделяет память.<br>
3. Третье замечание экзотическое&#33; :) Оказалось, что в OS Android память функцией calloc() выделяется оригинальным образом - вне зависимости от реального наличия свободной RAM. Например, на смартфоне с 2Гб RAM, из которой свободно 1.4Гб RAM, можно выделить и 3Гб, и почти 4Гб RAM&#33; И даже расставить в этой виртуальной памяти метки&#33;<br>
Например, у меня в 32bit Android 5.0 память перестала выделяться (calloc() выдала NULL) только при запросе массива RAM более 4Гб.<br>
Справедливости ради, в честных Linux-ах с выделением памяти все нормально - ОС следит за тем, чтобы запрашиваемый кусок RAM действительно был в наличии.<br>
В Андроиде использовался компилятор C/C++ c4droid. <br>
<br>
Итак, всем спасибо за советы&#33;<br>
Проблема решена.<br>
<br>
P.S. Это была вторая проблема при построении эффективного алгоритма решения Задачи Коммивояжера (ЗК).<br>
Первый вопрос, который я задавал, был о возможности решения ЗК в 32bit ОС Linux, но с использованием технологии PAE (это оказалось невозможным).<br>
<a class='tag-url' href='http://forum.sources.ru/index.php?act=Select&nav=au&CODE=show&searchid=bf689b36b875595f7d754af548deeaab&search_in=posts&result_type=posts' target='_blank'>http://forum.sources.ru/index.php?act=Sele...sult_type=posts</a><br>
Третья проблема, которую я собираюсь решить, - использовать многоядерность современных процессоров для решения ЗК. Например, на Intel Core i7 2600K собираюсь в 8 раз сократить время расчетов за счет распараллеливания вычислений.<br>
И, наконец, в-четвертых, собираюсь попробовать решать эти задачи в OS Windows. В отличии от OS Linux операционки от Microsoft раньше были очень плохо приспособлены для решения подобного рода задач. Главная проблема, которую я здесь у MS обнаружил, - неконтролируемый сброс огромных массивов данных в SWAP. Сами понимаете, что при этом становится с временами решения ЗК&#33; Это провал&#33; Посмотрим, что стало нового в этом вопросе в Windows 7 и в Windows 10&#33;]]></description>
        <author>mkudritsky</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738691</guid>
        <pubDate>Sat, 02 Sep 2017 12:55:50 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738691</link>
        <description><![CDATA[mkudritsky: Господа, всем спасибо за подсказки.<br>Как я сам не додумался&#33; Тут ведь все достаточно просто:<br>1. Заранее расчитать размер и одним движением запросить сразу огромный кусок памяти и указатель на его начало.<br>Кстати, так будет несложно и контролировать возможность выделения нужного &quot;куска&quot; памяти значением функции calloc()<br>2. Уже в имеющемся куске памяти просто расставить указатели нужным мне образом&#33;<br>Все&#33;<br><br>Вижу максимум 2-3 обращения к функции calloc()<br>И, кстати, все запрашиваемые массивы памяти будут многократно кратны степени 2:<br>1. Массив базисов указателей на данные каждого состояния.<br>Размер: ziseof(sG*)*2**(Ng) - куда уж кратнее степени 2.<br><br>2. Массив данных для каждого состояния.<br>Размер: sizeof(sG)*Ng*2**(Ng-1) - тоже самое многократно кратен 2.<br><br>В общем, пока беру тайм-аут.<br>Тоже иногда надо отдыхать&#33;<br>В ближайшее время доложу о результатах.]]></description>
        <author>mkudritsky</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738686</guid>
        <pubDate>Sat, 02 Sep 2017 11:52:05 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738686</link>
        <description><![CDATA[JoeUser: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=411266&view=findpost&p=3738652'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>mkudritsky &#064; <time class="tag-quote__quoted-time" datetime="2017-09-02T03:34:09+00:00">02.09.17, 03:34</time></span><div class='quote '>Почему память функцией calloc() выделяется не &quot;плечом к плечу&quot;, а с &quot;дырами&quot;?</div></div><br>
Попробуй выделять большой кусок (или куски) самостоятельно - их и пользуй. Выделение памяти - операция небыстрая. Сократив количество &quot;выделений&quot; - ускоришь выполнение, и избавишься от &quot;дырок&quot;.]]></description>
        <author>JoeUser</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738682</guid>
        <pubDate>Sat, 02 Sep 2017 11:09:11 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738682</link>
        <description><![CDATA[amk: Напиши функции доступа, или класс-посредник, которые и будут извлекать тебе нужную информацию.]]></description>
        <author>amk</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738668</guid>
        <pubDate>Sat, 02 Sep 2017 09:43:05 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738668</link>
        <description><![CDATA[mkudritsky: Спасибо всем ответившим&#33;<br>
Стало немного понятно. Сам я на C/C++ работаю всего два года, да и то - только с прикладными задачами типа Задачи Коммивояжера.<br>
До этого всю жизнь работал на Pascal...<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">#include &#60;stdlib.h&#62;</div><div class="code_line">#include &#60;stdio.h&#62;</div><div class="code_line">//-------------------------------------</div><div class="code_line">&nbsp;</div><div class="code_line">typedef struct {// Структура со свойствами города текущего состояния</div><div class="code_line">&nbsp;char sNg; // Номер города нижележащего состояния, куда оптимально надо идти из текущего состояния. Принадлежит базису текущего состояния!</div><div class="code_line">&nbsp;unsigned short Smin; // Минимальная длина пути коммивояжера в текущее состояние</div><div class="code_line">} sG;</div><div class="code_line">&nbsp;</div><div class="code_line">// typedef char sG[3]; // Первый байт - номер города текущего состояния; и 2+3 байты - минимальная длина пути коммивояжера в текущее состояние</div><div class="code_line">//-------------------------------------</div></ol></div></div></div></div><br>
(Остальное - без изменений)<br>
<br>
Теперь память выделяется так, если использовать структуру:<br>
1. Ng=25 Реально=2308Мб, Lsost=1946<br>
С массивом было: Реально=1685Мб, Lsost=1527Мб<br>
<br>
2. Ng=26 Реально=4744Мб, Lsost=4027Мб<br>
С массивом было: Реально=4000Мб, Lsost=3154Мб<br>
<br>
ВЫВОД: все равно для хранения данных с описанием состояний выгодно использовать массив char sG[3], а не структуру.<br>
Памяти для работы программы с массивом расходуется меньше.<br>
<br>
Тут есть еще один вопрос... Касательно работы с чтением/записью данных.<br>
А. С номером города, в котором находится коммивояжер в текущем состоянии все просто:<br>
sG.sNg - это при работе со структурой<br>
sG[0] - а это при работе с массивом.<br>
<br>
Б. А вот с кратчайшим путем в текущее состояние все сложнее.<br>
sG.Smin - со структурой-то все просто&#33;<br>
А вот при работе с массивом этот Smin должен вытягиваться из двух байт, начиная с sG[1]<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">unsigned short *Smin=(unsigned short*)(Ns[iSostDn][0]+1);</div><div class="code_line">unsigned short Sprom=*Smin+Smatr[m][j];</div></ol></div></div></div></div><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">unsigned short *Smin=(unsigned short*)(Ns[iSost][j-k]+1);</div><div class="code_line">*Smin=S1;</div></ol></div></div></div></div><br>
<br>
И мне такой код не кажется элегантным.<br>
Боюсь, что пройдет пару лет и я уже не смогу расшифровать, как в этой части программа работает&#33;<br>
Нельзя ли как-то поэлегантнее указать, что адрес переменной unsigned short Smin совпадает с адресом Ns[][]+1 (то есть вторым элементом массива sG[3])?<br>
Пробовал здесь задействовать union, но что-то не получилось у меня - все данные динамические...]]></description>
        <author>mkudritsky</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738664</guid>
        <pubDate>Sat, 02 Sep 2017 08:47:09 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738664</link>
        <description><![CDATA[leo: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=411266&view=findpost&p=3738652'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>mkudritsky &#064; <time class="tag-quote__quoted-time" datetime="2017-09-02T03:34:09+00:00">02.09.17, 03:34</time></span><div class='quote '>Почему память функцией calloc() выделяется не &quot;плечом к плечу&quot;, а с &quot;дырами&quot;?</div></div><br>
Это особенность работы менеджера динамической памяти. Не знаю как в gcc, а в msvc в 32-битном приложении каждый блок памяти, выделяемый calloc, new и т.п., во-первых, содержит служебный заголовок размером 8 байт, во-вторых, сам размер выделяемого блока округляется вверх до границы 8 байт. Отсюда и &quot;дыры&quot;. Плюс к этому, менеджер динамической памяти (кучи), запрашивает&#092;резервирует память у ОС блоками с определенной гранулярностью (в Win - кратно 64 Кб) и не может размещать данные, выделенные одним calloc, в разных блоках. Поэтому возможны доп. &quot;дыры&quot; в конце&#092;хвосте этих зарезервированных блоков, если ни один из запрашиваемых размеров calloc не умещается в оставшийся &quot;хвост&quot; ни одного их зарезервированных блоков памяти. <br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=411266&view=findpost&p=3738657'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>mkudritsky &#064; <time class="tag-quote__quoted-time" datetime="2017-09-02T06:45:13+00:00">02.09.17, 06:45</time></span><div class='quote '>К сожалению, как видим, ОС Linux за кампанию с gcc не позволяют упаковать данные максимально плотно.<br>
Неужели нельзя задать gcc никакие ключи?</div></div><br>
При использовании стандартных аллокаторов памяти ключи врядли помогут. Единственный способ - использовать собственный менеджер памяти, который будет резервировать память у ОС средствами АПИ (в винде через VirtualAlloc) и выделять ее под струкутры&#092;массивы приложения без лишних накладных расходов (заголовков и выравниваний размеров), свойственных стандартным аллокаторам.]]></description>
        <author>leo</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738660</guid>
        <pubDate>Sat, 02 Sep 2017 08:20:33 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738660</link>
        <description><![CDATA[amk: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=411266&view=findpost&p=3738657'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>mkudritsky &#064; <time class="tag-quote__quoted-time" datetime="2017-09-02T06:45:13+00:00">02.09.17, 06:45</time></span><div class='quote '>К сожалению, как видим, ОС Linux за кампанию с gcc не позволяют упаковать данные максимально плотно.Неужели нельзя задать gcc никакие ключи?Для меня пока важна экономия памяти, а не быстродействие...</div></div> Кое-что задавать там можно, но возможности ограничены упаковкой памяти внутри структуры. Сама структура всё равно будет выравниваться на границу, кратную степени 2<br>
Так что если надо упаковывать максимально плотно, придётся паковать вручную.<br>
<br>
Однако, подозреваю, такое уплотнение позволит добавить всего один, максимум два, города.]]></description>
        <author>amk</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738657</guid>
        <pubDate>Sat, 02 Sep 2017 06:45:13 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738657</link>
        <description><![CDATA[mkudritsky: К сожалению, если свойства текущего состояния коммивояжера объявить как структуру (см. закомментированный фрагмент кода в начале программы), то такая структура будет занимать аж 4 байта. Хотя переменные структуры<br>sG.sNg - 1 байт, текущий город, в котором находится коммивояжер.<br>sG.Smin - 2 байта, минимальный путь, ведущий в текущее состояние<br>занимают всего 3 байта.<br><br>Впрочем, об этом написано в учебниках по C/C++, то есть структуры выравниваются компилятором по 2, 4, 8, 16 и т.п. байт - для оптимизации кода.<br>Именно поэтому мне пришлось объявлять свойства состояния sG так, как это объявлено в программе.<br><br>К сожалению, как видим, ОС Linux за кампанию с gcc не позволяют упаковать данные максимально плотно.<br>Неужели нельзя задать gcc никакие ключи?<br>Для меня пока важна экономия памяти, а не быстродействие...<br><br>P.S. Только что добрался до ПЭВМ с 16Гб RAM и провел вычисления для 27 городов:<br>Ng=27, реально требуемая память - около 8208Мб, переменная Lsost - 6510Mb.]]></description>
        <author>mkudritsky</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738653</guid>
        <pubDate>Sat, 02 Sep 2017 04:20:43 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738653</link>
        <description><![CDATA[Славян: Всё потому, что:<br>В идеале структура sG занимает 3 байта (1+2), а выделять по 3 байта ОС будет только в особо сложных/крайних своих состояниях. Т.о. выделит некое большее кратное двойке.<br>Если не идеал, то компилятор увидит, что структура sG занимает кратное двойке памяти (вроде стало лучше), и тогда расхождений в числах не будет. Но для этого надо, чтобы ОС умела выделять такие крохотные куски, кои согласованы с градацией компилятора.]]></description>
        <author>Славян</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738652</guid>
        <pubDate>Sat, 02 Sep 2017 03:34:09 +0000</pubDate>
        <title>Дыры при выделении памяти для решения Задачи Коммивояжера</title>
        <link>https://forum.sources.ru/index.php?showtopic=411266&amp;view=findpost&amp;p=3738652</link>
        <description><![CDATA[mkudritsky: При решении комбинаторной Задачи Коммивояжера создается много состояний.<br>
Количество состояний растет экспоненциальным образом с ростом числа городов, которые надо обойти коммивояжеру.<br>
Каждое состояние хранит в RAM свои данные.<br>
<br>
Для каждого состояния память выделяется функцией языка C calloc()<br>
В конце программы выделенная память освобождается функцией free()<br>
<br>
Вот программа, демонстрирующая выделение памяти в Задаче Коммивояжера.<br>
Выделенная память (главные массивы) считается переменной Lsost <br>
Расчеты проводились в OS Runtu 16.04 64bit (клон Ubuntu). В ПК установлено 8Гб RAM.<br>
Компиляция проводилась командой:<br>
<br>
&#036;gcc -std=c11 ZKmass.c<br>
<br>
ZKmass.c<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">#include &#60;stdlib.h&#62;</div><div class="code_line">#include &#60;stdio.h&#62;</div><div class="code_line">//-------------------------------------</div><div class="code_line">/*</div><div class="code_line">struct sG {// Структура со свойствами города текущего состояния</div><div class="code_line">&nbsp;char sNg; // Номер города нижележащего состояния, куда оптимально надо идти из текущего состояния. Принадлежит базису текущего состояния!</div><div class="code_line">&nbsp;unsigned short Smin; // Минимальная длина пути коммивояжера в текущее состояние</div><div class="code_line">};</div><div class="code_line">*/</div><div class="code_line">typedef char sG[3]; // Первый байт - номер города текущего состояния; и 2+3 байты - минимальная длина пути коммивояжера в текущее состояние</div><div class="code_line">//-------------------------------------</div><div class="code_line">int &nbsp;Ng, Nc, &nbsp;// Число городов коммивояжера и число состояний (Nc=2**Ng)</div><div class="code_line">&nbsp;&nbsp; &nbsp; iSost, &nbsp; // Адреса базисов состояний</div><div class="code_line">&nbsp;&nbsp; &nbsp; *bNg; &nbsp; &nbsp;// Массив &quot;битов&quot;, соответствующих номерам городов</div><div class="code_line">sG **Ns; &nbsp; &nbsp; &nbsp;// Массив состояний коммивояжера (не более Ng*2**(Ng-1))</div><div class="code_line">unsigned long long int Lsost; &nbsp; // Счетчик размера всей необходимой структуры (в байтах</div><div class="code_line">//-------------------------------------------------------------------------------------------------</div><div class="code_line">&nbsp;</div><div class="code_line">int main(void) {</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// Размер структуры</div><div class="code_line">&nbsp;printf(&quot;Размер структуры sG = %lu\n&quot;, sizeof(sG));</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// Задание числа городов</div><div class="code_line">&nbsp;printf(&quot;Число городов Ng = &quot;);</div><div class="code_line">&nbsp;scanf(&quot;%d&quot;,&amp;Ng);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// Нахождение числа базисов состояний (2**Ng)</div><div class="code_line">&nbsp;Nc=1;</div><div class="code_line">&nbsp;Nc=(Nc&#60;&#60;Ng); // Nc=2**Ng</div><div class="code_line">&nbsp;printf(&quot;Число базисов состояний Nc = %i\n&quot;, Nc);</div><div class="code_line">&nbsp;//</div><div class="code_line">&nbsp;// Задание вспомогательных массивов данных</div><div class="code_line">&nbsp;bNg=(int*)calloc(Ng,sizeof(int)); &nbsp;// Бит &#60;--&#62; город</div><div class="code_line">&nbsp;Ns=(sG**)calloc(Nc,sizeof(sG*)); &nbsp;// Массив базисов состояний. Значения - ссылки на массивы со свойствами городов состояний</div><div class="code_line">&nbsp;Lsost=Nc*sizeof(sG*); &nbsp; &nbsp; &nbsp;// такую RAM мы уже выделили (массив указателей размером Nc)</div><div class="code_line">&nbsp;printf(&quot;Размер структуры базисов сосотяний = %llu\n&quot;, Lsost);</div><div class="code_line">&nbsp;//</div><div class="code_line">&nbsp;// Заполнение битов-городов</div><div class="code_line">&nbsp;bNg[0]=1; // Для i-го города i-й бит в целой переменной типа int равен 1; остальные биты - 0</div><div class="code_line">&nbsp;for (int i=1; i&#60;Ng ; i++)</div><div class="code_line">&nbsp;&nbsp;bNg[i]=bNg[i-1]&#60;&#60;1;</div><div class="code_line">&nbsp;//</div><div class="code_line">&nbsp;// Построение всей структуры графа поиска. Выделение необходимой для расчетов памяти</div><div class="code_line">&nbsp;for (iSost=0; iSost&#60;Nc-1; iSost++) {</div><div class="code_line">&nbsp;&nbsp;int j1=0; // Начало вычисления кратности текущего состояния (подсчет ненулевых битов в числе iSost</div><div class="code_line">&nbsp;&nbsp;for (int j=0; j&#60;Ng; j++)</div><div class="code_line">&nbsp;&nbsp; if (iSost &amp; bNg[j]) j1++; // Счетчик увеличивается только на 1-битах</div><div class="code_line">&nbsp;&nbsp;Ns[iSost]=(sG*)calloc(Ng-j1,sizeof(sG)); // Выделена память для всех состояний с текущим базисом iSost</div><div class="code_line">&nbsp;&nbsp;Lsost+=(Ng-j1)*sizeof(sG); // Увеличен счетчик выделенной памяти</div><div class="code_line">&nbsp;}</div><div class="code_line">&nbsp;printf(&quot;Общий размер структуры состояний = %llu\n&quot;, Lsost);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;// Освобождение ранее выделенной памяти:</div><div class="code_line">&nbsp;free(bNg); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Освобождение массива битов-городов</div><div class="code_line">&nbsp;for (int j=0; j&#60;Nc-1; j++) // Освобождение структур поиска для каждого базиса состояний коммивояжера</div><div class="code_line">&nbsp;&nbsp; free(Ns[j]);</div><div class="code_line">&nbsp;free(Ns); &nbsp; // Удаление массива состояний (ссылки на структуру для каждого базиса)</div><div class="code_line">&nbsp;</div><div class="code_line">} // Завершение программы main</div></ol></div></div></div></div><br>
<br>
Так в чем, собственно, проблема?<br>
А проблема вот в чем:<br>
1. Для числа городов Ng=25 переменная Lsost показывает, что выделяется примерно 1527Мб RAM.<br>
Однако в Диспетчере задач памяти выделяется 1685Мб - более чем на 100Мб превышает ожидаемую величину.<br>
<br>
2. Дальше - больше. :(<br>
Для числа городов Ng=26 переменная Lsost показывает, что выделяется примерно 3155Мб RAM.<br>
Однако в Диспетчере задач памяти выделяется 4000Мб - уже почти на 1Гб превышает ожидаемую величину.<br>
<br>
Вот и возникает вопрос: почему это памяти при решении Задачи Коммивояжера затрачивается существенно больше, чем я ожидаю?<br>
Почему память функцией calloc() выделяется не &quot;плечом к плечу&quot;, а с &quot;дырами&quot;?<br>
Может компилятор как-то выравнивает выделяемую память по каким-то сегментам?<br>
<br>
P.S. Та же картина наблюдается, если программу переписать на C++, соотвественно заменив calloc/free на new/delete и компилировать программу командой:<br>
&#036;c++ -m64 ZKmass.cpp]]></description>
        <author>mkudritsky</author>
        <category>C/C++: Общие вопросы</category>
      </item>
	
      </channel>
      </rss>
	