Увеличить размер стека основной программы или создать новый поток с большим размером стека для блоков рекурсивного кода? - PullRequest
0 голосов
/ 06 июня 2019

У меня следующий вопрос к Каков размер стека потока BackgroundWorker DoWork?Есть ли способ изменить это?

Должен ли я увеличить размер стека моей основной программы, используя следующее событие после сборки:

"$(DevEnvDir)..\..\VC\bin\editbin.exe" /STACK:8388608 "$(TargetPath)"

или я должен заключить в капсулу свой блок рекурсивного кодав новом потоке с большим размером стека?

Thread thread = new Thread(delegate()
{
    // do work with larger stack size
}, 8192 * 1024);
thread.Start();
thread.Join();

Код, который имеет много рекурсии, взят из Intel MKL - функции LAPACKE_dtrtri , которую я вызываю через DLLImport.Поэтому я не могу изменить этот код.Я могу просто изменить размер стека, чтобы избежать ошибки переполнения стека.

  • Каков недостаток в назначении большего размера стека моей основной программе?

  • В чем недостаток создания новой нити с большим размером стека для этого расчета?

  • Какое решение лучше?

  • Какой будет разумный размер стека?8 МБ, 16 МБ, 32 МБ или 64 МБ (например, MATLAB )?Программа работает на компьютерах с ОЗУ не менее 16 ГБ (до 256 ГБ).

Примечание: для 99% моего приложения размер стека по умолчанию составляет 4 МБ (64-бит) было бы достаточно, но другой 1% использует внешний код, который является сильно рекурсивным.

1 Ответ

0 голосов
/ 12 июня 2019
  • Какое решение лучше?
  • Какое решение лучше?

Первый подход с использованием editbin в событии после сборки завершается неудачей при использовании ключа строгого имени для подписи сборки. После изменения сборки с помощью editbin проверка подписанной сборки не удастся. sn.exe -v assembly.exe вернет Failed to verify assembly -- Strong name validation failed ...

Смотрите также:

Использование события AfterCompile и отставка сборки - это обходной путь (который я сейчас использую). Файл проекта должен содержать следующие строки:

  <Target Name="AfterCompile">
    <Exec Command="
&quot;$(DevEnvDir)..\..\VC\bin\editbin.exe&quot; /STACK:16777216 &quot;$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)&quot;
&quot;$(FrameworkSDKDir)bin\NETFX 4.5.1 Tools\sn.exe&quot; -Ra &quot;$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)&quot; &quot;$(SolutionDir)\STRONGNAME.snk&quot;
" />
  </Target>
  <PropertyGroup>
    <PostBuildEvent>REM "See AfterCompile for stack size and resigning"</PostBuildEvent>
  </PropertyGroup>

Я узнал о событии после компиляции, когда читал следующий ответ: https://stackoverflow.com/a/22617361/7556646

Второй подход , но для программы отверстий, а не только для блоков рекурсивного кода, будет выглядеть так:

static class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        Thread thread = new Thread(delegate()
        {
            Main2(args);
        }, 16 * 1024 * 1024);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        thread.Join();
    }

    static void Main2(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(app);
    }
}

Второй подход имеет тот недостаток, что размер стека события BackgroundWorker DoWork по-прежнему составляет 1 МБ (32-разрядный или любой) или 4 МБ (64-разрядный).

Смотрите также:

  • В чем недостаток создания нового потока с большим размером стека для этого вычисления?
  • Какой будет разумный размер стека?

См. Комментарии Ганса Пассанта.

...