0 / 0 / 0
Регистрация: 17.03.2012
Сообщений: 11
1

Билдер и 4 ядра

17.03.2012, 23:02. Показов 4774. Ответов 26
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
У меня 4-х ядерный процессор, и я использую CodeGear C++ Builder 11.

Приложение, над которым я работаю, вычислительноёмкое, и я хотел бы использовать процессор по максимуму.

Но когда открываю Windows Task Manager, вижу, что потребляется лишь 25% процессорного времени. Есть подозрение, что задействуется только одно ядро, хотя может быть просто в билдере стоит ограничение.

Вопрос: как сделать так, чтоб использовалось 90% процессора?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.03.2012, 23:02
Ответы с готовыми решениями:

нетбук с каким процом лучше n550(2 ядра )или C-50(2 ядра )?
всем привет решил в следюющем году сдать егэ по инфе => надо готовится и учить програмирование а...

Помогайте выбрать: видюха 640М и проц i7 2.4Гц (4 ядра) или 750M и i7 2Гц (2 ядра) ?
Приветствую. Вот занес уже руку в кошелек для покупки ноута Acer ASPIRE V5-572G но тот...

Что выбрать: Intel 2 ядра или AMD 4 ядра?
Нужен дельный совет от гуру! Могу взять АМД проц 4 ядра, либо интеловский 2 ядерный, цена примерно...

Что будет лучше i7 2630qm (2 Гц 4 ядра) vs i5 3230m (2,6 Гц 2 ядра) ?
Что будет лучше i7 2630qm (2 Гц 4 ядра) vs i5 3230m (2,6 Гц 2 ядра) ? Не использую программы...

26
1565 / 1491 / 248
Регистрация: 19.02.2010
Сообщений: 4,047
17.03.2012, 23:18 2
Нет, в Билдере ограничений не стоит.
Надо "вручную" запрограммировать распределение вычислений на несколько потоков.
Курите либо класс TThread, либо виндовозовские апишные функции (CreateThread() и прочие).
0
Эксперт С++
2348 / 1721 / 149
Регистрация: 06.03.2009
Сообщений: 3,675
17.03.2012, 23:19 3
Цитата Сообщение от Zolden Посмотреть сообщение
Есть подозрение, что задействуется только одно ядро, хотя может быть просто в билдере стоит ограничение.
Подозрение правильное, но билдер не причем.
Цитата Сообщение от Zolden Посмотреть сообщение
Вопрос: как сделать так, чтоб использовалось 90% процессора?
Производить вычисление сразу в несколько потоков, для чего написать соответствующий код. Луше приэто заюзать какую-нибудь либу, которая это дело облегчит.
0
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.03.2012, 23:23 4
TThread лучше наверное в нем синхронизация с компонентами реализована.
Как я понимаю если приложение однопоточно то выполняется оно с одинаково независимо от кол-ва ядер(тобиш выигрыша 0)
И не факт что программу можно "разложить" на потоки.
0
0 / 0 / 0
Регистрация: 17.03.2012
Сообщений: 11
17.03.2012, 23:33  [ТС] 5
Потоки, значит...

Спасибо, попробую.

Вроде должно получиться: у меня там массив объектов, и каждый объект вычисляется независимо.

Значит, первым делом стоит TThread попробовать?
0
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
18.03.2012, 01:47 6
Да читай Архангельского у него есть описание TThread ( как в принципе и ф-ций WinApi для потоков)
0
36 / 36 / 8
Регистрация: 10.11.2011
Сообщений: 94
18.03.2012, 12:24 7
увеличивать процессорное время выделяемое программе

код есть на Delphi, проблем переписать на С++ не составит
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
             procedure TForm1.Button1Click(Sender: TObject); 
             var 
               ProcessID : DWORD; 
               ProcessHandle : THandle; 
               ThreadHandle : THandle; 
             begin 
               ProcessID := GetCurrentProcessID; 
               ProcessHandle := OpenProcess(PROCESS_SET_INFORMATION, 
                                            false, 
                                            ProcessID); 
               SetPriorityClass(ProcessHandle, REALTIME_PRIORITY_CLASS); 
               ThreadHandle := GetCurrentThread; 
               SetThreadPriority(ThreadHandle, THREAD_PRIORITY_TIME_CRITICAL); 
             end;
0
Технофашист
228 / 216 / 11
Регистрация: 11.03.2009
Сообщений: 887
18.03.2012, 13:00 8
Потоки, значит...

Спасибо, попробую.

Вроде должно получиться: у меня там массив объектов, и каждый объект вычисляется независимо.

Значит, первым делом стоит TThread попробовать?
Помимо потоков придется изучать примитивы синхронизации (семафоры, каналы и т.д.), без этого никак.
Если ищешь более легкий путь, то советую использовать технологию MPI, которая как раз и создана для распараллеливания вычислительноемких задач. По сложности изучения, что MPI, что потоки примерно одинаковы, но вот использовать MPI гораздо проще и приятнее. К тому же, можно распараллеливать и на несколько компов.
Если заинтересовало, то советую Реализация MPICH2 - http://parallel.ru/vvv/mpi.html
0
0 / 0 / 0
Регистрация: 17.03.2012
Сообщений: 11
19.03.2012, 22:49  [ТС] 9
Всем спасибо за советы. Я использовал TThread и получил полную загрузку. Это оказалось не сложно, так что библиотеки использовать видимо не буду.

А вот совет ББК, которому я последовал в первую очередь, не помог, что не удивительно: если в программе явно не расписана многопоточность, то воспользоваться дополнительными процессорами она не может, какой ты ей приоритет ни поставь.

darkAngel, а упомянутые тобой примитивы синхронизации для чего используются? Про них у Архангельского не было упомянуто, поэтому я сделал по-простому: 4 потока, в каждом обрабатываю 1/4 массива объектов, а пятый, главный, поток следит, чтоб эти 4 потока выполнились, и тогда переходит к следующему циклу.
0
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
19.03.2012, 23:11 10
если в программе явно не расписана многопоточность, то воспользоваться дополнительными процессорами она не может, какой ты ей приоритет ни поставь.
Зато может вытеснять процессы других программ тем самым выполняться быстрее.

У Архангельского несколько книг в одной он TThread описывает и там есть о возможности этого класса синхронизировать доступ потоков к vcl- компонентам

В другой книге (более продвинутой) дается описание WinApi -ф-ции и объектов синхронизации доступа к ресурсам (мютексы,семафоры,события и тп)

Самое скверное это то что без синхронизации прога поначалу может работать нормально, но в непредвиденных ситуациях напрочь заглючивать.
0
0 / 0 / 0
Регистрация: 17.03.2012
Сообщений: 11
20.03.2012, 16:24  [ТС] 11
Avazart, а как называется эта "более продвинутая" книга?

Я сначала распараллелил независимое вычисление объектов, и всё работало нормально. Но потом распараллелил взаимодействие объектов, при котором они обращаются к полям друг друга, и всё стало зависать в произвольный момент времени.

Похоже, надо разбираться в семафорах и прочем.
0
1123 / 794 / 101
Регистрация: 01.02.2011
Сообщений: 1,880
Записей в блоге: 1
20.03.2012, 19:18 12
Цитата Сообщение от Zolden Посмотреть сообщение
Но потом распараллелил взаимодействие объектов, при котором они обращаются к полям друг друга, и всё стало зависать в произвольный момент времени.
попробуй EnterCriticalSection и LeaveCriticalSection, по описанию вроде подходят, сам их не пробовал.
0
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
20.03.2012, 19:38 13
Avazart, а как называется эта "более продвинутая" книга?
Архангельский "Приемы программирования в С++ Builder 6 и 2006" стр171
0
0 / 0 / 0
Регистрация: 17.03.2012
Сообщений: 11
21.03.2012, 20:03  [ТС] 14
Цитата Сообщение от Avazart Посмотреть сообщение
Архангельский "Приемы программирования в С++ Builder 6 и 2006" стр171
Чё-та не нашёл я этой книги. Ссылочку не подкинешь?

Хотя, мне кажется, что я исправил ситуацию. К сожалению, пришёл к решению интуитивно, а не в результате понимания ситуации. Может кто подскажет, почему всё зависало?

А дело вот в чём. Мне казалось, что зависания эти происходят вовсе не из-за обращения к одному и тому же ресурсу. Потому что во-первых, данные читались, а не записывались, а во-вторых, зависания происходили либо с самого начала (после единиц циклов), либо в конце, когда популяция обсчитываемых объектов значительно уменьшалась. В остальное время всё отлично работало, а значит потоки не конфликтовали при чтении данных.

И случайно я нашёл решение. Мне надо было понизить приоритет главного потока, чтоб цикл ожидания не мешал дочерним потокам считать объекты. И вдруг оказалось, что если поставить главному потоку минимальный приоритет, программа виснет сразу и в 100% случаев. А если дать ему максимальный приоритет, то программа не виснет.

А было всё вот как организовано (опишу в псевдокоде):

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
главный поток::Execute(){
    while (!terminated){
        подготовить данные // нераспараллеленная часть цикла
        запустить n дочерних потоков // распараллеленная часть цикла
        ждать пока все дочерние потоки засуспендятся
    }
}
 
дочерний поток::Execute(){
    while (!terminated){
        обсчёт объектов
        Suspend()
    }
}
Эта схема приводила к зависаниям. Уточню, что то что я тут называю зависаниями, представляло собой ситуацию, когда один из дочерних потоков не засуспендился, и все ждут его.

И, собственно, вот как я поменял процедуру главного потока:

C++
1
2
3
4
5
6
7
8
9
главный поток::Execute(){
    while (!terminated){
        подготовить данные // нераспараллеленная часть цикла
        запустить n дочерних потоков // распараллеленная часть цикла
        Priority = tpIdle
        ждать пока все дочерние потоки засуспендятся
        Priority = tpTimeCritical
    }
}
И с этими сменами приоритета виснуть перестало. Кто-то может это объяснить?
0
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
21.03.2012, 22:56 15
Чё-та не нашёл я этой книги. Ссылочку не подкинешь?
Она у меня в бумаге, в интернете не встречал её
0
1123 / 794 / 101
Регистрация: 01.02.2011
Сообщений: 1,880
Записей в блоге: 1
22.03.2012, 17:14 16
Цитата Сообщение от Zolden Посмотреть сообщение
ждать пока все дочерние потоки засуспендятся
как код этого процесса выглядит?
0
0 / 0 / 0
Регистрация: 17.03.2012
Сообщений: 11
22.03.2012, 17:59  [ТС] 17
Цитата Сообщение от kzru_hunter Посмотреть сообщение
как код этого процесса выглядит?
вот:
переменная "с" становится ложью если все потоки засуспенжены

C++
1
2
3
4
5
6
bool c = true;
while (c){
    for (i = 0; i < nthreads; i++)      // nthreads - кеоличество потоков
        c = c && t[i]->Suspended;   // t - массив указателей на потоки
    c = !c;
}
Но дело, мне кажется, не в этом коде, он-то честно отслеживает факт засуспенженности, но по какой-то причине дочерний поток остаётся незасуспенженным, хотя в его цикле есть вызов Suspend()

Кстати, после упомянутого мною в предыдущем посте нововведения с приоритетами, ситуация таки возникает, но никогда вначале, а только в том случае, когда число объектов становится небольшим, порядка десяти штук.

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

Avazart
Ладно, я у Шилдта нашёл эту тему.
0
1123 / 794 / 101
Регистрация: 01.02.2011
Сообщений: 1,880
Записей в блоге: 1
22.03.2012, 20:11 18
Zolden этот цикл грузил основной поток.

Попробуй так (пример использования объекта события):
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
DWORD WINAPI ThreadFunc( LPVOID id );
HANDLE hEvent;
volatile g_nthreads = 12;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        hEvent = CreateEvent(NULL, False, False, NULL);
        int nthreads = g_nthreads;
 
        for ( int i = 0; i < nthreads; i++ )
                CreateThread(NULL, 0, ThreadFunc, 0, 0, 0);
 
        WaitForSingleObject(hEvent, INFINITE);  // æäåì, ïîêà g_nthreads ñòàíåò ðàâíûì íóëþ è âûçîâåòñÿ ôóíêöèÿ SetEvent
 
        ShowMessage("Ãîòîâî");
}
//---------------------------------------------------------------------------
 
DWORD WINAPI ThreadFunc(LPVOID id)
{
        // ---------- âû÷èñëåíèÿ ------------
        //...
        // ----------------------------------
 
        g_nthreads--;
        if (g_nthreads == 0) SetEvent(hEvent);
 
        return 0;
}
0
0 / 0 / 0
Регистрация: 17.03.2012
Сообщений: 11
23.03.2012, 19:40  [ТС] 19
kzru_hunter

Спасибо за код, кое-что новое для себя узнал.

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

Поэтому я просто заменил свой вариант ожидания на предложенную тобой функцию WaitForSingleObject().

И снова программа начала виснуть: возникает ситуация, когда ни один из потоков не выполняется, но WaitForSingleObject не получает события продолжить работу. Ума не приложу, в чём дело.

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

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
53
54
55
56
57
58
59
60
61
62
const int nthreads = 4;
volatile int threads_counter;
HANDLE hEvent;
 
class cyclethread: public TThread{  // класс дочернего потока
private:
    int a, b;
protected:
    void __fastcall Execute(){
        while (!Terminated){
            if (b > a)
                calc_units(a, b);   // вычисления, производимые потоком
            threads_counter--;
            if (threads_counter == 0)
                SetEvent(hEvent);
            Suspend();
        }
    }
public:
    __fastcall cyclethread(bool CreateSuspended): TThread(CreateSuspended){
    }
    void setab(int aa, int ab){
        a = aa;
        b = ab;
    }
};
 
class mainthread: public TThread{   // класс главного потока
private:
    cyclethread *t[nthreads];
protected:
    void __fastcall Execute(){
        while (!Terminated){
            threads_counter = nthreads;
            the_cycle();    // нераспараллеленная часть вычислений
            int i;
            if (units.size() > 0)
                for (i = 0; i < nthreads; i++){
                    t[i]->setab(units.size() * i/nthreads, units.size() * (i + 1)/nthreads);    // тут дочернему потоку выделяется часть массива для обработки
                    t[i]->Resume();
                }
            WaitForSingleObject(hEvent, INFINITE);
        }
    }
public:
    __fastcall mainthread(bool CreateSuspended) : TThread(CreateSuspended){
        int i;
        for (i = 0; i < nthreads; i++)
            t[i] = new cyclethread(true);
        hEvent = CreateEvent(NULL, false, false, NULL);
    }
    __fastcall killthreads(){
        int i;
        for (i = 0; i < nthreads; i++)
            TerminateThread((void *)t[i]->Handle, 0);
    }
    __fastcall ~mainthread(){
        int i;
        for (i = 0; i < nthreads; i++)
            delete t[i];
    }
};
0
1365 / 732 / 67
Регистрация: 28.01.2011
Сообщений: 2,064
23.03.2012, 19:48 20
Цитата Сообщение от Zolden Посмотреть сообщение
Чё-та не нашёл я этой книги. Ссылочку не подкинешь?
В переплете я купил на ozon.ru.
0
23.03.2012, 19:48
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.03.2012, 19:48
Помогаю со студенческими работами здесь

Что выбрать? 2 ядра 3100 Мгц или 4 ядра 1100 Мгц
Господа помогите с выбором ноутбука. Выбираю из этих двух: 1....

Конструкторы С++ Билдер
Здравствуйте программисты! Скажите пожалуйста, это правда,что конструктор предназначен для...

Задача по Си Билдер
Нужно создать програму для решения функции 1(1+(sqr(sin(x+y)))/(2-abs(x)))+x . Буду благодарен за...

Портативный С++ Билдер
Ребята, скажите, где можно скачать портативный С++ БИЛДЕР 6, очень при очень нужно. Пробовал...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

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