Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: qtest от Июнь 17, 2013, 23:08



Название: Многопоточное вычисление функции
Отправлено: qtest от Июнь 17, 2013, 23:08
Здравствуйте.
Есть работающий код, нормально выводящий результаты каждого потока по отдельности, как синхронизовать их для вывода в одну переменную в мейне? Пытался читать про мьютексы и семафоры - ничего понятного не нашел.
Наиболее простой пример:
Код:
#include <QCoreApplication>
#include <QThread>


class thread : public QThread
{
public:
    int st,end,a,ans;
    int f(){
        int answ=0;
        for(int i=st;i<end;i++)
            answ+=a;
        return answ;
    }
    void run(){
        ans=f();
    }

};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    int a,n,m,i;
    scanf("%i %i %i",&a,&n,&m);
    int *d=new int[m];
    thread *t=new thread[m];

    for(i=0;i<m;i++){
        d[i]=(i+1)*n/m;
        if(i==0){
            t[i].st=0;
            t[i].end=d[i];
        }
        else if(i==(m-1)){
            t[i].st=d[i-1];
            t[i].end=n;
        }
        else{
            t[i].st=d[i-1];
            t[i].end=d[i];
        }
        t[i].a=a;

    }

    printf("\nstarted\n\n");

    for(i=0;i<m;i++)
        t[i].start(QThread::HighPriority);
   
    return app.exec();
}


Название: Re: Многопоточное вычисление функции
Отправлено: Авварон от Июнь 18, 2013, 00:19
Во-первыйх, юзайте QtConcurrent. Во-вторых... ну, вобщем, разберетесь.


Название: Re: Многопоточное вычисление функции
Отправлено: Igors от Июнь 18, 2013, 13:02
Здравствуйте.
Есть работающий код, нормально выводящий результаты каждого потока по отдельности, как синхронизовать их для вывода в одну переменную в мейне?
Может имелось ввиду "как накапливать сумму в main"? Если у Вас нитки запускаются один раз, то можно и без синхронизации
Код
C++ (Qt)
// ждем пока все нитки отработают
for(i = 0; i < m; i++)
  t[i].wait();
 
// суммирует результаты
int sum = 0;
for(i = 0; i < m; i++)
  sum += t[i].ans;
 


Название: Re: Многопоточное вычисление функции
Отправлено: qtest от Июнь 19, 2013, 11:11
Во-первыйх, юзайте QtConcurrent. Во-вторых... ну, вобщем, разберетесь.
Судя по описанию, он автоматически распараллеливает задачу на имеющееся количество ядер, это конечно даже эффективнее, но возможно ли самому указать количество потоков?
Может имелось ввиду "как накапливать сумму в main"? Если у Вас нитки запускаются один раз, то можно и без синхронизации
А если то же самое, но с накоплением суммы в глобальную переменную в самой f() и ее выводом в мейне? Т.е. цель - не столько решение конкретной задачи, сколько понимание мьютексов и семафоров.


Название: Re: Многопоточное вычисление функции
Отправлено: alex312 от Июнь 19, 2013, 11:28
, но возможно ли самому указать количество потоков?
http://qt-project.org/doc/qt-5.0/qtcore/qthreadpool.html#globalInstance


Название: Re: Многопоточное вычисление функции
Отправлено: Igors от Июнь 19, 2013, 11:49
А если то же самое, но с накоплением суммы в глобальную переменную в самой f() и ее выводом в мейне? Т.е. цель - не столько решение конкретной задачи, сколько понимание мьютексов и семафоров.
Ну если "не выжимать скорость" то все очень просто
Код:
void run(){
    ans=f();
    QMutextLocker locker(&mutex);   // mutex должен быть напр глобальной переменной, т.е. один и тот же для всех ниток
    sum += ans;
}


Название: Re: Многопоточное вычисление функции
Отправлено: m_ax от Июнь 19, 2013, 12:35
Я бы курил в сторону std::future + std::async


Название: Re: Многопоточное вычисление функции
Отправлено: Авварон от Июнь 19, 2013, 13:48
Я бы курил в сторону std::future + std::async

Тот же конкурент, только убогий.


Название: Re: Многопоточное вычисление функции
Отправлено: Igors от Июнь 19, 2013, 13:55
Тоже мне "курцы"
Код
C++ (Qt)
#pragma omp parallel for reduction(+: sum)
for (int i = 0; i < limit; ++i)
sum += DoCalc(i);
 


Название: Re: Многопоточное вычисление функции
Отправлено: Old от Июнь 19, 2013, 14:22
Тоже мне "курцы"
Фи. По начитались букварей по OpenMP...
Где взрослый суровый велосипед? ;)


Название: Re: Многопоточное вычисление функции
Отправлено: qtest от Июнь 19, 2013, 15:48
Код:
#include <QCoreApplication>
#include <QThread>
#include <QMutex>

QMutex mutex;

int answer=0;

class thread : public QThread
{
public:
    int st,end,a,ans;
    int f(){
        int answ=0;
        for(int i=st;i<end;i++)
            answ+=a;
        return answ;
    }
    void run(){

        ans=f();
       // printf("\nst = %i, end = %i, result = %i",st,end,ans);
        mutex.lock();
        answer+=ans;
        mutex.unlock();
    }

};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    int a,n,m,i;
    scanf("%i %i %i",&a,&n,&m);
    int *d=new int[m];
    thread *t=new thread[m];

    for(i=0;i<m;i++){
        d[i]=(i+1)*n/m;
        if(i==0){
            t[i].st=0;
            t[i].end=d[i];
        }
        else if(i==(m-1)){
            t[i].st=d[i-1];
            t[i].end=n;
        }
        else{
            t[i].st=d[i-1];
            t[i].end=d[i];
        }
        t[i].a=a;

    }

    printf("\nstarted\n\n");

    for(i=0;i<m;i++)
        t[i].start(QThread::HighPriority);

    for(i=0;i<m;i++)
        t[i].wait();
    printf("\nAnswer = %i\n",answer);


    return app.exec();
}
Это правильно? Как можно сделать то же самое, но с помощью семафора, а не wait()?

Код:
QMutextLocker locker(&mutex);
answer+=ans;
Не работает, он делает то же самое?
Код:
  mutex.lock();
        answer+=ans;
        mutex.unlock();


Название: Re: Многопоточное вычисление функции
Отправлено: Old от Июнь 19, 2013, 15:51
Не работает...
Что значит не работает?


Название: Re: Многопоточное вычисление функции
Отправлено: Igors от Июнь 19, 2013, 16:52
Это правильно? Как можно сделать то же самое, но с помощью семафора, а не wait()?
QThread::wait - просто ждем когда нитка отработает, к мутексу это отношения не имеет

Не работает, он делает то же самое?
Да, то же самое и работать должно

Хотите потренироваться - возьмите задачу. Напр на семафоры:

- одна нитка читает символ (напр с клавы), другая нитка этот символ печатает

Фи. По начитались букварей по OpenMP...
Где взрослый суровый велосипед? ;)
Был, и даже вполне успешно боролся с реализацией gcc 4.4. Но против интеловской не устоял   :)


Название: Re: Многопоточное вычисление функции
Отправлено: qtest от Июнь 19, 2013, 18:18
Хотите потренироваться - возьмите задачу. Напр на семафоры:

- одна нитка читает символ (напр с клавы), другая нитка этот символ печатает
Код:
#include <QCoreApplication>
#include <QThread>
#include <QMutex>
QMutex mutex;
char c;

class rthread : public QThread
{
    void run(){
        for(;;){
        mutex.lock();
        c=getchar();
        mutex.unlock();
        }
    }
};

class wthread : public QThread
{
    void run(){
        for(;;){
        mutex.lock();
        putchar(c);
        mutex.unlock();
        }
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    rthread r;
    wthread w;
    r.start(QThread::HighPriority);
    w.start(QThread::HighPriority);
    printf("\nStarted\n\n");
    return a.exec();
}
Так?
Что значит не работает?
Код:
Mutext
Все работает, только не совсем понятно что и как он делает.




Название: Re: Многопоточное вычисление функции
Отправлено: Old от Июнь 19, 2013, 19:16
Все работает, только не совсем понятно что и как он делает.
Оно делает тоже что и ваш код, только безопасно. Эта конструкция никогда не забудет освободить ресурс, что нельзя сказать о человеке. :)


Название: Re: Многопоточное вычисление функции
Отправлено: Igors от Июнь 19, 2013, 19:22
Так?
Не так, если wthread первой захватит мутекс, она шлепнет char который еще не был введен. Не надо полагать что насовал мутексов побольше - и все дела.

Да, и откуда такая любовь к самому себе? (HighPriority)  :)


Название: Re: Многопоточное вычисление функции
Отправлено: qtest от Июнь 19, 2013, 20:35
Оно делает тоже что и ваш код, только безопасно. Эта конструкция никогда не забудет освободить ресурс, что нельзя сказать о человеке. :)
Это понятно, но в случае лок и анлок видно, где что открывается и где закрывается, а тут - не совсем.
Не так, если wthread первой захватит мутекс, она шлепнет char который еще не был введен. Не надо полагать что насовал мутексов побольше - и все дела.
Если убрать откуда-либо мутекс, путчар вообще будет работать без остановки.
Да, и откуда такая любовь к самому себе? (HighPriority)  :)
На всякий случай, может испортиться статистика какого-нибудь вывода. Это нежелательно?


Название: Re: Многопоточное вычисление функции
Отправлено: Igors от Июнь 20, 2013, 12:03
Если убрать откуда-либо мутекс, путчар вообще будет работать без остановки.
Так вот и используйте семафоры для остановки/синхронизации

На всякий случай, может испортиться статистика какого-нибудь вывода. Это нежелательно?
Да, нежелательно. Разве Вы наверняка знаете что именно эта нитка будет иметь больше работы? Нет, так зачем говорить ОС чаще отдавать упраление нитке все равно ждущей на getchar? Делайте по смыслу а не "на всякий случай"


Название: Re: Многопоточное вычисление функции
Отправлено: qtest от Июнь 21, 2013, 04:01
Так вот и используйте семафоры для остановки/синхронизации
Так вот в том и проблема, что семафоры я не понимаю, в самой первой программе тоже хотелось бы использовать их, а не вейт. Можете показать на этом примере как надо?


Название: Re: Многопоточное вычисление функции
Отправлено: Old от Июнь 21, 2013, 07:30
Так вот в том и проблема, что семафоры я не понимаю
Что именно не понимаете: как они работают или как их нужно использовать?
Напишите как вы понимаете их сейчас.


Название: Re: Многопоточное вычисление функции
Отправлено: Igors от Июнь 21, 2013, 08:18
Так вот в том и проблема, что семафоры я не понимаю, в самой первой программе тоже хотелось бы использовать их, а не вейт. Можете показать на этом примере как надо?
Что-то Вы слишком пассивны
Код
C++ (Qt)
// write thread
while (true) {
theSemaphore.acquire();
putchar(c);
...
}
 
Нитка ждет на закрытом cемафоре. Когда др нитка сделает  theSemaphore.release() cемафор откроется, сработает putchar и затем снова ожидание. Дальше сами