Pthreads - высокое использование памяти

я программирую что-то на C, которое создает много Pthreads в Linux в системе 256Mb. У меня обычно есть + 200Mb бесплатно.

когда я запускаю программу с низким количеством потоков, она работает, но как только я создаю около 100 потоков, она дает ошибки, потому что в системе заканчивается память. Я сделал несколько тестов, и каждый поток использует почти 2Mb. Размер стека потоков установлен в 16Kb.

код, который я использую для создания каждого потока:

pthread_attr_t attr;
pthread_attr_init(&attr);
size_t stacksize;
stacksize = (double) 16*1024;
int res = pthread_attr_setstacksize (&attr, stacksize);
int res2 = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (res != 0 || res2 != 0) {
    logs << "pthread_attr_XX: error "+int2string(res);
    exit(-1);
}
pthread_t id;
pthread_create(&id, &attr, &Class::thread_callback, &some_var);

это нормально или я что-то пропустила? Спасибо.

6 ответов


Не уверен, что это поможет, но попробуйте позвонить setrlimit с RLIMIT_STACK чтобы ограничить размер стека до 16k перед созданием первого потока.


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


Да, это довольно распространено для почти любой операционной системы, чтобы задохнуться и умереть на таком количестве потоков. Это не проблема, что создатели ОС (Linux или иначе) уделили много внимания, так как очень немногие системы имеют столько процессоров, поэтому ваш код вряд ли будет выполняться намного быстрее с 100 потоками, чем с 8 (или сколько у вас есть процессоров).

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


почему stacksize = (double) 16*1024; ? Это целое число.

попробуйте установить его в 32 или 64 килобайта, потому что 16 * 1024 может быть не разрешено; в стеке также может быть TLS (даже вы не используете TLS; библиотеки, включая libc).

так, измените строку

stacksize = 64*1024; 

и проверьте, сколько памяти потребляется.


Если вы хотите более низкие накладные расходы, рассмотрите технологии потоковой обработки пользовательского пространства, такие как волокна, ALA co-operative task management.

http://en.wikipedia.org/wiki/Fiber_(вычислительная_техника)

http://www.evanjones.ca/software/threading.html

GNU Portable threads:

http://www.gnu.org/software/pth/

Boost C++ co-routines:

http://www.boost.org/doc/libs/1_60_0/libs/coroutine/doc/html/index.html

Windows-только волокна как FYI:

http://msdn.microsoft.com/en-us/library/ms682661 (v=против 85).aspx

посмотреть Википедию ссылку на пример реализации.


может быть, это причина:

"(признание утечки

Если вы создаете объединяемый поток, но забываете присоединиться к нему, его ресурсы или частная память всегда хранятся в пространстве процесса и никогда не восстанавливаются. Всегда присоединяйтесь к соединяемым потокам; не присоединяясь к ним, вы рискуете серьезными утечками памяти.)"

читать здесь: http://www.ibm.com/developerworks/library/l-memory-leaks/