Подтвердить что ты не робот

Как установить stacksize с С++ 11 std:: thread

Я пытался познакомиться с библиотекой std:: thread в С++ 11 и пришел к камню преткновения.

Изначально я пришел из фона posix threads и задавался вопросом, как установить размер стека std:: thread до построения, так как я не могу найти ссылок на выполнение такой задачи.

С помощью настроек pthreads размер стека выполняется следующим образом:

void* foo(void* arg);
.
.
.
.
pthread_attr_t attribute;
pthread_t thread;

pthread_attr_init(&attribute);
pthread_attr_setstacksize(&attribute,1024);
pthread_create(&thread,&attribute,foo,0);
pthread_join(thread,0);

Есть ли что-то подобное при использовании std:: thread?

Я использовал следующую ссылку:

http://en.cppreference.com/w/cpp/thread

4b9b3361

Ответ 1

Изначально я пришел из фона posix threads и задавался вопросом, как установить размер стека std:: thread до построения, так как я не могу найти ссылок на выполнение такой задачи.

Вы не можете. std::thread не поддерживает это, потому что std::thread стандартизирован, а С++ не требует, чтобы машина даже имела стек, а тем более - фиксированный размер.

pthreads более ограничительны с точки зрения аппаратного обеспечения, которое они поддерживают, и предполагает, что существует определенный фиксированный размер стека для потока. (Таким образом, вы можете настроить это)

Ответ 2

Как уже сказал Loki Astari, на самом деле очень редко требуется размер стека не по умолчанию и обычно либо ошибка, либо результат плохого кодирования.

  • Если вам кажется, что размер стека по умолчанию слишком велик для ваших нужд и хочет его уменьшить, просто забудьте об этом. Каждая современная ОС теперь использует фиксацию виртуальной памяти/по требованию, что означает, что память зарезервирована, а не фактически выделена, до тех пор, пока вы не получите доступ к страницам. Уменьшение размера стека будет не уменьшать фактический объем памяти.

  • Из-за такого поведения ОС могут позволить установить размер стека по умолчанию для очень больших значений. Например. на ванильном Debian это 8MB (ulimit -s), которого должно быть достаточно для каждой потребности. Если вам все же удастся преодолеть этот предел, моя первая идея будет заключаться в том, что ваш код неправильный, поэтому вам следует в первую очередь рассмотреть его и переместить вещи в кучу, преобразовать рекурсивные функции в циклы и т.д.

  • Если, несмотря на все это, вам действительно нужно изменить размер стека (т.е. увеличить его, так как уменьшить его бесполезно), на POSIX вы всегда можете использовать setrlimit в начале вашей программы, чтобы увеличить размер стека по умолчанию. Конечно, это повлияет на все потоки, но только те, кто в ней нуждается, фактически будут использовать дополнительную память.

  • И последнее, но не менее важное: со всей справедливостью я вижу угловой случай, когда уменьшение размера стека имеет смысл: если у вас много потоков в 32-битной системе, они могут съесть ваше виртуальное адресное пространство ( опять же, а не фактическое потребление памяти) до такой степени, что у вас недостаточно адресного пространства для кучи. Опять же, setrlimit является вашим другом, хотя я бы посоветовал перейти на 64-битную систему, чтобы извлечь выгоду из большего виртуального адресного пространства (и если ваша программа что в любом случае, вы, вероятно, тоже выиграете от дополнительной ОЗУ).

Ответ 3

Я нашел это в книге Скотта Мейерса Overview of the New C++(C++0x), так как довольно долго я не могу опубликовать его в качестве комментария, это полезно?

Существует также стандартный API для доступа к платформе обрабатывает потоки, мьютексы, переменные состояния и т.д. Эти считается, что ручки являются механизмом определения приоритетов потоков, установки размеров стека и т.д. (Что касается размеров установочных стеков, Anthony Уильямс отмечает: "Из тех ОС, которые поддерживают установку размера стека, все они делают это по-другому. Если вы кодируете определенную платформу (так что использование native_handle будет в порядке), тогда вы можете использовать это платформа для переключения стеков. например на POSIX вы могли бы используйте makecontext и swapcontext вместе с явным распределением стек, а в Windows вы можете использовать Fibers. Затем вы можете использовать платформы (например, флаги компоновщика), чтобы установить значение по умолчанию размер стека на что-то действительно крошечное, а затем переключить стеки на что-то большее, если необходимо".)

Ответ 4

Я также изучал эту проблему. Для некоторых приложений размер стека по умолчанию не является достаточным. Примеры: программа выполняет глубокую рекурсию в зависимости от конкретной проблемы, которую она решает; программе необходимо создать много потоков, и потребление памяти будет проблемой.

Вот резюме (частичных) решений/обходных решений, которые я нашел:

  • g++ поддерживает опцию -fsplit-stack в Linux. См. для получения дополнительной информации о Сплит-стеках. Вот резюме с их сайта:

Цель разделенных стеков - разрешить несмежный стек, который автоматически вырабатывается автоматически. Это означает, что вы можете запускать несколько потоки, каждая из которых начинается с небольшого стека, а стек растет и в соответствии с требованиями программы.

Примечание: -fsplit-stack работал только после того, как я начал использовать золотой линкер . Кажется, clang++ также поддерживает этот флаг. Версия, которую я попробовал (clang++ 3.3), разбилась при попытке скомпилировать мое приложение с помощью флага -fsplit-stack.

  • В Linux установите размер стека, выполнив ulimit -s <size> перед запуском приложения. size - размер стека в Kbs. Замечание: команда unlimit -s unlimited не повлияла на размер потоков, созданных с помощью std::thread. Когда я использовал ulimit -s unlimited, основной поток мог расти, но потоки, созданные с помощью std::thread, имели размер по умолчанию.

  • В Windows с использованием Visual Studio мы можем использовать параметр linker /STACK или /STACKSIZE в файле определения модуля, это размер по умолчанию для всех созданных потоков. Для получения дополнительной информации см. эту ссылку. Мы также можем изменить этот параметр в любом исполняемом файле, используя инструмент командной строки EDITBIN.

  • В Windows с использованием mingw g++ мы можем использовать опцию -Wl,--stack,<size>. По какой-то причине при использовании cygwin g++ этот флаг влияет только на размер основного потока.

Подходы, которые сделал, не работают для меня:

  • ulimit -s <size> в OSX. Он влияет только на размер основного потока. Более того, Mac OSX по умолчанию для размера стека pthread составляет 512 КБ.

  • setrlimit влияет только на размер основного потока в Linux и OSX. На cygwin он никогда не работал у меня, кажется, что он всегда возвращает ошибку.

Для OSX единственная альтернатива, по-видимому, использует boost::thread вместо std::thread, но это не хорошо, если мы хотим придерживаться стандарта. Надеюсь, что g++ и clang++ также будут поддерживать -fsplit-stack в OSX в будущем.

Ответ 5

Ищет ответ на этот вопрос прямо сейчас.

Похоже, что хотя std:: thread не поддерживает это, boost:: thread does.

В частности, вы можете использовать boost:: thread:: attributes, чтобы выполнить это:

boost::thread::attributes attrs;
attrs.set_size(4096*10);
boost::thread myThread(attrs, fooFunction, 42);