В общем, да, стеки [пользовательского пространства] - по одному на поток, тогда как куча обычно используется всеми потоками. См., Например, этот вопрос о Linux. Однако в некоторых операционных системах (ОС) на Windows, в частности, даже однопоточное приложение может использовать более одной кучи. Использование OpenMP для потоковой передачи не меняет этих основ, которые в основном зависят от операционной системы. Поэтому, если вы не сузите свой вопрос до конкретной ОС, на этом уровне обобщения нельзя сказать больше.
Поскольку мне лень самому рисовать это, вот сравнительная иллюстрация из Программирование PThreads Николса и др. (1996) ![введите описание изображения здесь](https://i.stack.imgur.com/jZRm8.gif)
Несколько более подробная (и, к сожалению, потенциально более запутанная) диаграмма находится в бесплатном LLNL Учебное пособие по программированию потоков POSIX Б. Барни.
И да, как вы правильно подозреваете, выполнение большего количества потоков требует больше памяти стека. Фактически вы можете исчерпать виртуальное адресное пространство процесса с помощью стеки ниток, если их достаточно. В различных реализациях OpenMP есть переменная среды STACKSIZE. (или около), который контролирует, сколько стека OpenMP выделяет для потока.
Что касается вопроса / предложения Z boson о локальном хранилище потоков (TLS): грубо (то есть концептуально) говоря, Локальное хранилище потоков - это куча для каждого потока. Существуют отличия от кучи для каждого процесса в API, используемом для управления им, по крайней мере потому, что каждому потоку нужен свой собственный отдельный указатель на свой собственный TLS, но в основном у вас есть подобный куче фрагмент адресного пространства процесса, который зарезервирован к каждому потоку. TLS не является обязательным, вам не нужно его использовать. OpenMP предоставляет собственную абстракцию / директиву для TLS -подобные постоянные данные для каждого потока, называемые THREADPRIVATE
. Необязательно, чтобы OpenMP THREADPRIVATE
использовал поддержку TLS операционной системы, однако есть Linux- специализированный документ, в котором говорится, что такая реализация дает наилучшую производительность, по крайней мере, в этой среде.
И вот тонкость (или почему я сказал «грубо говоря», когда сравнивал TLS с кучей по потокам): предположим, что вам нужна куча по потокам, скажем, чтобы уменьшить конкуренцию за блокировку основной кучи. На самом деле вам не нужно хранить всю кучу для каждого потока в TLS каждого потока. Достаточно сохранить в TLS каждого потока отдельный указатель заголовка на кучи, выделенные в общем пространстве для каждого процесса. Идентификация и автоматическое использование куч по потокам в программе (для уменьшения конфликтов блокировок в основной куче) - это чрезвычайно сложная проблема CS. Распределители кучи, которые делают это автоматически, называются масштабируемыми / параллельными [izing] распределителями кучи или около того. Например, Intel TBB предоставляет один такой распределитель, и он можно использовать в вашей программе, даже если вы больше ничего не используете из TBB. Хотя некоторые люди, кажется, считают, что распределитель Intel TBB содержит черную магию, на самом деле он не сильно отличается от вышеупомянутой базовой идеи использования TLS для указания на некоторую локальную кучу потока, которая, в свою очередь, состоит из нескольких двусвязных списков, разделенных по блокам. / object-size, как на следующих диаграммах из Документ Intel о TBB иллюстрирует: ![введите описание изображения здесь](https://i.stack.imgur.com/WJ5yM.png)
У IBM есть нечто похожее на AIX 7.1, но немного более сложное. Вы можете указать его (по умолчанию) распределителю использовать фиксированное количество куч для многопоточных приложений, например MALLOCOPTIONS=multiheap:3
. AIX 7.1 также имеет другой вариант (который можно объединить с multiheap) _ 4_, что несколько похоже на то, что делает Intel TBB, в том, что он поддерживает поточный кеш освобожденных регионов, из которых будущие запросы на выделение могут обслуживаться с меньшей конкуренцией за глобальную кучу. Помимо этих опций для распределителя по умолчанию, AIX 7.1 также имеет (не по умолчанию) " Распределитель Watson2 ", который" использует специфичный для потока механизм, который использует различное количество структур кучи, которое зависит от поведения программы. Поэтому параметры конфигурации не требуются. " (Но вам нужно явно выбрать этот распределитель с помощью MALLOCTYPE=Watson2
.) Работа Watson2 звучит даже ближе к тому, что делает распределитель Intel TBB.
Вышеупомянутые два примера (Intel TBB и AIX), подробно описанные выше, предназначены только как конкретные примеры, но не должны восприниматься как содержащие какой-то эксклюзивный соус. Идея кеширования кучи на поток или процессор / arena / журнал довольно широко распространен. В статье о jemalloc BSDcan цитируется 1998 MS Research как первая систематическая оценка арен для этой цели. Вышеупомянутый документ MS ссылается на веб-страницу ptmalloc как «посещенную 11 мая 1998 г.» и резюмирует работу ptmalloc следующим образом: «Он использует связанный список подкучков, где каждая подкуча имеет блокировку, 128 свободных списков и некоторую память для управления. . Когда потоку необходимо выделить блок, он сканирует список подгрудей и захватывает первую разблокированную, выделяет требуемый блок и возвращается. Если он не может найти разблокированную подкучину, он создает новую и добавляет ее в список. Таким образом, поток никогда не ждет в заблокированной подкуче ".
person
Fizz
schedule
21.01.2015