С Новым годом! Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.51/59: Рейтинг темы: голосов - 59, средняя оценка - 4.51
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 6
1

Не получается создать более 382 потоков

19.04.2009, 11:52. Показов 11077. Ответов 17
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
нужно создать много нитей. Не хочет создавать более 382 потоков. на 383ем возвращает 12 = ENOMEM = out of memory
Проблемма: нужно создать значительно большее кол-во потоков.
Вопрос: out of какой memory. RAM ещё хватает с головой.

gcc-4.2.4
linux-2.6.27.8

запускал на разных машинах и разных дистрибутивах. Везде одна и та же ошибка на одном и том же потоке

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <pthread.h>
#define threads=1000;
void* some_func(void* arg)
{
    std::cout<<"i'm thread #"<<(int)arg<<"\n";
    pthread_exit(NULL);
}
int main()
{
    int thread_error;
    int args[threads];
    for (int i=0;i<threads;i++)
        {args[i]=i;}
    for (int thread_num=0; thread_num<threads; thread_num++)
    {
        pthread_t thread_id;
        std::cout<<"begin to create thread #"<<thread_num<<"\n";
        thread_error=pthread_create(&thread_id, NULL, some_func,(void*)args[thread_num]);
 
        if (thread_error!=0)
            {std::cout<<"error #"<<thread_error<<"\n";}
    }
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.04.2009, 11:52
Ответы с готовыми решениями:

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

Нужно сделать чтобы в цикле работало не более 10-ти потоков
Доброго времени. Возник коллапс мыслительного процесса. Прошу помощи или совета... Есть цикл...

Не получается объединить более 2 строк
- должно быть - получается &lt;HTML&gt;&lt;HEAD&gt; &lt;TITLE&gt;пример таблицы&lt;/TITLE&gt; &lt;/HEAD&gt;&lt;BODY&gt; ...

Ремонт Посудомойка ZANUSSI DCS-382 Stydio Line, нужна инструкция пользователя
Всех с новым годом. мужики есть механична посудомойка нужна инструкция пользователя а то дружина...

17
577 / 571 / 65
Регистрация: 29.01.2009
Сообщений: 1,274
19.04.2009, 11:59 2
Макрос вобще-то так определяется
Код
#define THREADS 1000
Без ";".
0
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 6
19.04.2009, 12:00  [ТС] 3
в оригинале его нет . перепечатывал ручками с монитора. нечайно вырвалось.
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
19.04.2009, 14:50 4
такую проверь
Вложения
Тип файла: zip pthread.zip (362 байт, 210 просмотров)
0
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 6
19.04.2009, 17:07  [ТС] 5
безрезультатно
0
Evg
Эксперт CАвтор FAQ
21280 / 8304 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
19.04.2009, 17:16 6
Возможно, что проблема в следующем. Поток - это по сути новый процесс, но который имеет общую глобальную память с родительским процессом, но свой собственный стек. При этом все потоки живут в одном и том же виртуальном адресном пространстве. На каждый стек intel'овский вариант линуха выделяет что-то порядка 8 мегов памяти. Помножить на 382 - это более 3 гигов. Наверняка линух у тебя 32-битный, т.е. на один процесс отводится максимум 4 гига виртуальной памяти. ОС не в состоянии полностью динамически выделать память под разные части адресного пространства - это делается более-менее статически. Т.е. начиная с какого-то адреса жёстко выделается место под mmap и динамические библиотеки, начиная с какого-то адреса жёстко выделается место под стеки и т.п. Но вот таким количеством потоков скорее всего исчерпался выделенны лимит адресного пространства под стеки.

Решений вижу два:
1. Установить 64-битную версию линуха
2. Перекомпилять ядро, поменяв в настройках ограничение на стек одного процесса. Последствия, думаю, сам понимаешь - для всех остальныз процессов ты порежешь пользовательский стек. Какие-то большие программы с глубоким стеком вызова в теории начнут ломаться на исполнении
1
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 6
19.04.2009, 18:59  [ТС] 7
очень даже вариант. Насколько я знаю в посиксовых нитях при их создании можно задавать длину стека самостоятельно. Так что скорее всего ядро дёргать не придётся. Буду пробывать.
0
Evg
Эксперт CАвтор FAQ
21280 / 8304 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
19.04.2009, 19:24 8
Цитата Сообщение от prestigio Посмотреть сообщение
очень даже вариант. Насколько я знаю в посиксовых нитях при их создании можно задавать длину стека самостоятельно. Так что скорее всего ядро дёргать не придётся. Буду пробывать.
Это видимо дёргать напрямую системный вызов clone (или clone2, если таковой на i386 присутсвует). Правда через клоны чем плохо, что самому надо следить за этими тредами (а так это делает менеджер внутри библиотеки libpthread). Хотя в современных линуксах вместо libpthread уже используется nptl, возможно, что там возможностей для настройки больше
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
20.04.2009, 00:54 9
prestigio, 12 = ENOMEM = out of memory, память проверил ?

Цитата Сообщение от prestigio
запускал на разных машинах и разных дистрибутивах.
на каких например ?
а один поток запускал на них ?

Добавлено через 59 секунд
Код
[guest@station ~]$ uname -a
Linux station.domain 2.6.23.1-42.fc8 #1 SMP Tue Oct 30 13:55:12 EDT 2007 i686 athlon i386 GNU/Linux
[guest@station ~]$
0
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 6
20.04.2009, 16:11  [ТС] 10
запускал всё на (хотя это особо не важно) :
Linux slax 2.6.27.8 #1 SMP Sun Dec 7 08:30:31 Local time zone must be set--see zic m i686 Intel(R) Celeron(R) M CPU 440 @ 1.86GHz GenuineIntel GNU/Linux
Linux debian 2.6.18-6-486 #1 Sun Feb 10 22:06:33 UTC 2008 i686 GNU/Linux
Linux slax 2.6.27.8 #1 SMP Sun Dec 7 08:30:31 Local time zone must be set--see zic m i686 AMD Duron(tm) processor AuthenticAMD GNU/Linux

>>Это видимо дёргать напрямую системный вызов clone
оказалось всё намного проще. можно просто pthread_attr_setstacksize();

обрубал размер стека по корень. загнулся на 52'587 тредах с сообщением "killed". Скорее всего некая защита от своего рода мусорных бомб. Треды то непрерывно в цикле шпарю. В общем и целом ляпота. Работает.
0
Evg
Эксперт CАвтор FAQ
21280 / 8304 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
20.04.2009, 20:37 11
Цитата Сообщение от prestigio Посмотреть сообщение
>>Это видимо дёргать напрямую системный вызов clone
оказалось всё намного проще. можно просто pthread_attr_setstacksize();
В старых libpthread этого ещё не было. Однако разработчики исправили недочёты

Цитата Сообщение от prestigio Посмотреть сообщение
обрубал размер стека по корень. загнулся на 52'587 тредах с сообщением "killed". Скорее всего некая защита от своего рода мусорных бомб. Треды то непрерывно в цикле шпарю. В общем и целом ляпота. Работает.
Тут скорее похоже на ограничение по числу процессов
0
0 / 0 / 0
Регистрация: 02.09.2009
Сообщений: 12
11.09.2009, 14:29 12
А сколько нужно в pthread_attr_setstacksize(); указать? Какой размер стека?

Добавлено через 12 минут
Цитата Сообщение от glob() Посмотреть сообщение
А сколько нужно в pthread_attr_setstacksize(); указать? Какой размер стека?
Глупый вопрос. Уже понял.
0
3 / 3 / 0
Регистрация: 09.01.2009
Сообщений: 41
02.10.2009, 05:25 13
CONFIG_4KSTACKS на х86_32
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <pthread.h>
#include <limits.h>
 
#define THREADS 1024
pthread_mutex_t ptex = PTHREAD_MUTEX_INITIALIZER;
 
void *some_func(void *arg) {
        printf("i'm thread # %d\n", (long )&arg);
        pthread_exit(NULL);
}
 
int main(void)
{
        int i;
        int thread_num;
        int thread_error;
        int pid_num;
        pthread_t thread_id;
        pthread_attr_t pattr;
        int glob_count = 0;
        int args[THREADS*THREADS];
 
        for ( i = 0; i < THREADS; i++) {
           args[i] = i;
        }
        pthread_attr_setstacksize(&pattr, 1);
        pthread_attr_init(&pattr);
 
        for ( pid_num = 0; pid_num < THREADS; pid_num++) {
           if ( !fork() ) {
               for ( thread_num = 0; thread_num < 400; thread_num++)  {
                     printf("begin to create thread # %d\n", glob_count);
                     thread_error = pthread_create(&thread_id, 
                                                                &pattr, 
                                                                some_func, 
                                                               (void *)args[glob_count]);
                        if (thread_error != 0 ) {
                                printf("error # %d\n", thread_error);
                        }
                pthread_mutex_lock(&ptex);
                   glob_count++;
                pthread_mutex_unlock(&ptex);
               }
           }
        }
return 0;
}
В общам мысль ясна, спать ушёл...

Добавлено через 25 минут
Ах да, самое интересное


Bash
1
2
3
4
# cat /proc/sys/kernel/threads-max 
64481
 
# sysctl -w kernel.threads-max=1661992959;  :)
Добавлено через 25 минут
Шайтай деатачед версия.

делать ulimit -s 100 обязательно

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
 
#define THREADS 99999
 
int i;
 
void run(void) {
 
   char c;
   if (i < 10)
      printf("Адрес = %u KB\n", (unsigned int) &c / 1024);
   sleep(60 * 60);
}
 
int main(int argc, char *argv[]) {
 
   int terr = 0;
 
   pthread_attr_t pattr;
   pthread_attr_setstacksize(&pattr, 128);
   pthread_attr_init(&pattr);
 
   pthread_t thread[THREADS];
 
   for (i = 0; i < THREADS && terr == 0; i++) {
 
       terr = pthread_create(&(thread[i]), &pattr, (void *) &run, NULL);
          if (terr == 0) {
             pthread_detach(thread[i]);
              if (( i + 1) % 1000 == 0)
                 printf("%i ниткоф ...\n", i + 1);
           }
          else
               printf("шухер, вернулся %i от нитки нумбер %i.\n",terr, i + 1);
   }
 
 return 0;
}
Добавлено через 41 минуту
Около 31.000 запустилось :-P

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
 
#define THREADS 32768
 
int i;
 
void run(void) {
 
   char c;
   if (i < 10)
      printf("Адрес = %u KB\n", (unsigned int) &c / 1024);
   sleep(60 * 60);
}
 
int main(int argc, char *argv[]) {
 
   int terr = 0;
   pthread_attr_t pattr;
 
   void *stackbase;
 
   int size = 0x200;
 
   stackbase = (void *) malloc(size);
 
 
   pthread_attr_init(&pattr);
   pthread_attr_setstacksize(&pattr, size);
   pthread_attr_setstack(&pattr, stackbase, size);
 
   pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
 
   pthread_t thread[THREADS];
 
   for (i = 0; i < THREADS && terr == 0; i++) {
 
       terr = pthread_create(&(thread[i]), &pattr, (void *) &run, NULL);
          if (terr == 0) {
             pthread_detach(thread[i]);
              if (( i + 1) % 1000 == 0)
                 printf("%i ниткоф ...\n", i + 1);
           }
          else
               printf("шухер, вернулся %i от нитки нумбер %i.\n",terr, i + 1);
   }
 
 free(stackbase);
 return 0;
}
0
garryTheHotDog
05.03.2010, 22:55 14
а как вычислить необходимы размер стека для потока?? или только опытным путем?
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
05.03.2010, 23:52 15
garryTheHotDog, а не нужно ничего вычислять. размера по умолчанию хватает.
вам известно, что помещается в стек, и каким образом используется память стека?
0
garryTheHotDog
06.03.2010, 11:16 16
А если я хочу его уменьшить...работает очень много потоков...по умолчанию слишком велик!
Evg
Эксперт CАвтор FAQ
21280 / 8304 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
06.03.2010, 11:30 17
Цитата Сообщение от garryTheHotDog Посмотреть сообщение
а как вычислить необходимы размер стека для потока?? или только опытным путем?
Можно и математическим путём. Прикидываешь, сколько места в стеке будет отжирать каждая процедура и какие будут процедуры. Если не представляешь, как это делается, то только опытным путём
0
Эксперт С++
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
06.03.2010, 15:30 18
Цитата Сообщение от garryTheHotDog Посмотреть сообщение
работает очень много потоков
это говорит только о неправильной проектировке/структуре проекта!
есть такой термин как "пул потоков"(thread pool), почитайте.

вот скажите, для чего столько потоков?
0
06.03.2010, 15:30
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.03.2010, 15:30
Помогаю со студенческими работами здесь

Не получается выставить более 60 Герц на мониторе
Доброго времени суток Вам. Столкнулся с такой проблемой, не могу выставить более 60-ти Герц на...

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

Не получается принять TCP/IP пакет более 2048 байт. Visual C++.
Использую MFC. Имеется UDP-сокет (CAsyncSocket). При приходе пакета длиной более 2048 байт функция...

Как создать много потоков?
Как создать потоки циклом?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru