Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.55/22: Рейтинг темы: голосов - 22, средняя оценка - 4.55
68 / 56 / 14
Регистрация: 20.12.2013
Сообщений: 542
1

Многопоточное матрично-векторное произведение

24.10.2014, 09:15. Показов 4118. Ответов 14
Метки нет (Все метки)

Доброго времени суток.
Хочу написать многопоточный вариант матрично-векторного произведения. Единственное, что приходит на ум, - в методе класса при вызове создавать потоки (CreateThread) и в конце ждать окончания выполнения всех потоков (WaitForMultipleObjects), т.е., как всегда и поступал. Но вот есть подозрения, что быстродействия не получится - в каждом произведении заново создавать/удалять потоки, наверно, затратно? Как поступить?

Добавлено через 10 часов 8 минут
upd
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.10.2014, 09:15
Ответы с готовыми решениями:

Найти скалярное и векторное произведение векторов
Вот программка для операций над векторами, но почему-то не хочет работать, посмотрите плиз: ...

Векторное произведение векторов, в чем ошибка?
векторное произведение векторов в чем ошибка? #include <iostream> using namespace std; int...

Как одновременно декларировать векторное и скалярное произведение векторов?
В обоих случаях умножается вектор на вектор. Нельзя же перегрузить по типу значения.

Матрично-векторное произведение без хранения матрицы
Добрый день! Подскажите, пожалуйста, как написать handle функцию матрично-векторного произведения...

14
Эксперт по математике/физикеЭксперт С++
1944 / 1281 / 368
Регистрация: 16.05.2013
Сообщений: 3,344
Записей в блоге: 6
24.10.2014, 09:32 2
Цитата Сообщение от AndrSlav Посмотреть сообщение
Но вот есть подозрения, что быстродействия не получится - в каждом произведении заново создавать/удалять потоки, наверно, затратно? Как поступить?
Пулы потоков.
Цитата Сообщение от AndrSlav Посмотреть сообщение
Единственное, что приходит на ум, - в методе класса при вызове создавать потоки (CreateThread) и в конце ждать окончания выполнения всех потоков (WaitForMultipleObjects), т.е., как всегда и поступал.
Мы в разделе С++. Здесь мы говорим о реализации многопоточности в стандартной библиотеке. Если принципиально использование реализации многопоточности от Windows то вы переедете в соответствующий раздел.
1
68 / 56 / 14
Регистрация: 20.12.2013
Сообщений: 542
24.10.2014, 19:55  [ТС] 3
Цитата Сообщение от Ilot Посмотреть сообщение
Если принципиально использование реализации многопоточности от Windows
Не принципиально. Важно только быстродействие.
0
Эксперт С++
1669 / 1041 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
24.10.2014, 22:06 4
Цитата Сообщение от AndrSlav Посмотреть сообщение
в каждом произведении заново создавать/удалять потоки, наверно, затратно?
Да, более чем.
Цитата Сообщение от AndrSlav Посмотреть сообщение
Как поступить?
Использовать Thread pool (пул потоков). Нужное число потоков запускается заранее и выполняет поставленные в очередь задания, а когда их нет - ждёт.
Если требуется, могу на следующей неделе поделиться своей простенькой реализацией Thread pool, которая основана на многопоточности из стандартной библиотеки (а значит, нужна поддержка со стороны компилятора, как C++11 так и собственно <thread>) и на очень полезных свойствах примитива Event из Windows API.
Разумеется, можно воспользоваться чем-то более серьёзным и сильным - в Boost::Asio есть свой thread pool, возможно и ещё где-то. Или можно написать свой.
1
Эксперт С++
4974 / 3082 / 456
Регистрация: 10.11.2010
Сообщений: 11,160
Записей в блоге: 10
24.10.2014, 22:15 5
Мне почему-то кажется, что если матрицы относительно не большого размера, то тут и пул потоков не поможет.
AndrSlav, можно немного конкретики?!
0
Эксперт С++
1669 / 1041 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
24.10.2014, 22:24 6
Цитата Сообщение от castaway Посмотреть сообщение
Мне почему-то кажется, что если матрицы относительно не большого размера, то тут и пул потоков не поможет.
Если у человека возникают мысли о многопоточности, то наверняка для этого есть какие-то основания. То ли матрицы большие, то ли их много, то ли вообще всё вместе. И в том, и в другом случае задачу можно поделить на подходящие для пула потоков куски, будь то строки больших матриц или целиковое перемножение маленькой матрицы на вектор.
0
Эксперт С++
4974 / 3082 / 456
Регистрация: 10.11.2010
Сообщений: 11,160
Записей в блоге: 10
24.10.2014, 22:35 7
Цитата Сообщение от Nick Alte Посмотреть сообщение
Если у человека возникают мысли о многопоточности, то наверняка для этого есть какие-то основания.
Основания всегда есть. Но я говорил не об этом.
0
68 / 56 / 14
Регистрация: 20.12.2013
Сообщений: 542
24.10.2014, 23:01  [ТС] 8
Цитата Сообщение от castaway Посмотреть сообщение
можно немного конкретики?!
Нужно для решения СЛАУ в итерационном методе GMRES (гидродинамика). Пока еще далеко до завершения, так что матрицы небольшие, но, в принципе, размер не ограничен.
Цитата Сообщение от Nick Alte Посмотреть сообщение
Если требуется, могу на следующей неделе поделиться своей простенькой реализацией Thread pool
спасибо, очень бы пригодилось. На выходных буду разбираться с пулами потоков, но дополнительная информация всегда полезна.
0
68 / 56 / 14
Регистрация: 20.12.2013
Сообщений: 542
13.11.2014, 16:39  [ТС] 9
Как сделать, чтобы можно было сделать несколько вызовов функций с разными параметрами, с последующим ожиданием исполнения? Т.е. как передать данные в функцию submit. В примере выводится 1 2 2 2, а надо 1,1,2,2. Могу, конечно, приписать критические секции и статические переменные, но не хотел бы.
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
// ConsoleApplication7.cpp: определяет точку входа для консольного приложения.
//
 
#include "stdafx.h"
#include <iostream>
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
 
 
void NTAPI MyWorkCallback(PTP_CALLBACK_INSTANCE instance, void * context, PTP_WORK work)
{
    char* p= *((char**)context);
    printf("Hello %s", p);
    printf("\n");
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    char mas1[]= "1";
    char mas2[]= "2";
    char* p1= mas1;
    char** p= &p1;
   TP_WORK * work = CreateThreadpoolWork(MyWorkCallback, p, NULL);
    if (work == NULL)
        printf("Error %d in CreateThreadpoolWork", GetLastError());
    else {
        SubmitThreadpoolWork(work);
        WaitForThreadpoolWorkCallbacks(work, FALSE);
        SubmitThreadpoolWork(work);
        p1=mas2;
        SubmitThreadpoolWork(work);
        WaitForThreadpoolWorkCallbacks(work, FALSE);
        CloseThreadpoolWork(work);
    }
 
 
    char ch;
    std::cout<<*p;
    std::cin>>ch;
    return 0;
}
0
3656 / 2843 / 781
Регистрация: 25.03.2012
Сообщений: 10,429
Записей в блоге: 1
13.11.2014, 17:17 10
забыл один WaitForThreadpoolWorkCallbacks после 31й строчки, не?
0
68 / 56 / 14
Регистрация: 20.12.2013
Сообщений: 542
13.11.2014, 19:50  [ТС] 11
Kuzia domovenok, не правильно выразился: да можно поставить WaitForThreadpoolWorkCallbacks, но задача в том, чтобы несколько потоков выполнялись одновременно, а в этом случае просто будет очередь- смысл многопоточности теряется.

Добавлено через 1 час 14 минут
Вот так прокатывает, но неужели нет стандартного варианта?
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
#include "stdafx.h"
#include <iostream>
#include <windows.h>
 
CRITICAL_SECTION crSect1;
 
 
void NTAPI MyWorkCallback(PTP_CALLBACK_INSTANCE instance, void * context, PTP_WORK work)
{
 
    EnterCriticalSection(&crSect1);
  static int yy=-1;
  ++yy;
  LeaveCriticalSection(&crSect1);
    char** p= (char**)context;
    printf("Hello %s", p[yy]);
    printf("\n");
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    InitializeCriticalSection(&crSect1);
    char mas1[]= "1";
    char mas2[]= "2";
    char* p[2];
    p[0]= mas1;
    p[1]= mas2;
   TP_WORK * work = CreateThreadpoolWork(MyWorkCallback, p, NULL);
    if (work == NULL)
        printf("Error %d in CreateThreadpoolWork", GetLastError());
    else {
        SubmitThreadpoolWork(work);
        SubmitThreadpoolWork(work);
        WaitForThreadpoolWorkCallbacks(work, FALSE);
        CloseThreadpoolWork(work);
    }
 
 DeleteCriticalSection(&crSect1);
    char ch;
    std::cout<<*p;
    std::cin>>ch;
    return 0;
}
0
3656 / 2843 / 781
Регистрация: 25.03.2012
Сообщений: 10,429
Записей в блоге: 1
13.11.2014, 20:06 12
Цитата Сообщение от AndrSlav Посмотреть сообщение
Вот так прокатывает, но неужели нет стандартного варианта?
что ты хочешь, объясни. Ты передаёшь в потоки указатель на один и тот же аргумент p1, а потом удивляешься, что они с ним не могут одновременно работать?
Ну так передавай указатель на разные аргументы, что сказать...
0
68 / 56 / 14
Регистрация: 20.12.2013
Сообщений: 542
13.11.2014, 21:07  [ТС] 13
Kuzia domovenok, при обычном создании потоков передаю в функцию createthread исходные данные- одновременно работают n потоков. Здесь же почему-то в функцию SubmitThreadpoolWork нельзя передать данные, они есть только в callback функции, фигурирующей в вызове CreateThreadpoolWork.
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Ну так передавай указатель на разные аргументы, что сказать...
Т.е. делать вызов CreateThreadpoolWork несколько раз? А как в этом случае реализовать ожидание как в WaitForThreadpoolWorkCallbacks, чтобы при этом задачи выполнялись параллельно, а не последовательно?

Добавлено через 5 минут
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Ты передаёшь в потоки указатель на один и тот же аргумент p1, а потом удивляешься, что они с ним не могут одновременно работать?
В первом примере я ожидал, что в строке 31 будет прежнее значение, а в 33 уже новое. Ожидания не оправдались по понятным причинам, поэтому сделал как во втором посте, но хочу понять нельзя ли в более приличном виде написать.
0
68 / 56 / 14
Регистрация: 20.12.2013
Сообщений: 542
07.12.2014, 13:32  [ТС] 14
На всякий случай подниму тему.
Задача состоит не в том, чтобы создать несколько вообще разных потоков и запустить их параллельно, а создать несколько потоков с по сути одной функцией MyWorkCallback - для умножения матрицы на вектор (при каждом последующем вызове функции она должна работать со следующим диапазоном строк матрицы). Единственное, что пришло в голову, передавать в MyWorkCallback указатель на массив, чтобы при каждом вызове в критической секции увеличивалось значение статической переменной и так функция узнавала с каким участком матрицы работать.
Честно говоря, не нравится, что надо создавать отдельно массив с индексами в глобальной области. Как по-другому сделать?
0
68 / 56 / 14
Регистрация: 20.12.2013
Сообщений: 542
01.01.2015, 14:25  [ТС] 15
В продолжение темы, многопоточное умножение матрицы на вектор. Как думаете - нормально или проще можно сделать? (p.s. работает, но если скажете как лучше сделать, то буду рад )

Все в *h. файле:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct DATA_MATVEC
{
 DATA_MATVEC():MATR(0),VEC(0),REZ(0),nP(0){
                             InitializeCriticalSection(&crSect);
                             fWork = CreateThreadpoolWork(MyWorkCallback_MatVec, this, NULL);
                            };
 ~DATA_MATVEC() {
              DeleteCriticalSection(&crSect);
              CloseThreadpoolWork(fWork);
             };
 
 size_t nP;
 MATRIXX_LENTA<double>* MATR;    //Ленточная матрица - исходная
 VECTOR<double>* VEC;            //Множитель
 VECTOR<double>* REZ;            //Произведение
 CRITICAL_SECTION crSect;
 TP_WORK* fWork;
};
typedef DATA_MATVEC* PDATA_MATVEC;
 
static DATA_MATVEC mMatVec;      //Через этот экземпляр структуры происходит координация запусков MyWorkCallback_MatVec
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
void NTAPI MyWorkCallback_MatVec(PTP_CALLBACK_INSTANCE instance, void * context, PTP_WORK work)
{
 PDATA_MATVEC data= (PDATA_MATVEC)context;
 size_t nP= data->nP;
 CRITICAL_SECTION* crSect1= &(data->crSect);
 MATRIXX_LENTA<double>& MATR= *(data->MATR);
 VECTOR<double>& REZ= *(data->REZ);
 VECTOR<double>& VEC= *(data->VEC);
 size_t num= MATR.num;
 
  EnterCriticalSection(crSect1);      //Чтобы при последующих запусках MyWorkCallback_MatVec обрабатывался следующий кусок матрицы
  static size_t iP=-1;
  static size_t iN=0;
  ++iP;
  if(iP==0) REZ=0;
  size_t iPP=iP;
  LeaveCriticalSection(crSect1);
 
  size_t nnn= MATR.num/nP;
  size_t nnnL= MATR.num- (nP-1)*nnn;
  size_t numL;
 
  //Здесь вычисления для куска матрицы
 
 EnterCriticalSection(crSect1);
 ++iN;
 if(iN==nP){ iP=-1; iN=0;};               //Обнуление счетчика
 LeaveCriticalSection(crSect1);
};
Сама функция многопоточного перемножения матрицы и вектора
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename T>
 void MATRIXX_LENTA<T>::multiply_MatVecPool(VECTOR<T>& vec, VECTOR<T>& REZ, int nP)
 {
  mMatVec.MATR= this;
  mMatVec.VEC= &vec;
  mMatVec.REZ= &REZ;
  mMatVec.nP= nP;
 
     for(int i=0; i<nP; ++i) SubmitThreadpoolWork(mMatVec.fWork);
     WaitForThreadpoolWorkCallbacks(mMatVec.fWork, FALSE);
 
  return;
 };
Добавлено через 7 минут
Опаньки, поторопился, лучше бы в теме Многопоточное матрично-векторное произведение написал. Перенесите, пожалуйста, если не трудно.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.01.2015, 14:25

Векторное произведение
В кубе ABCDA1B1C1D1 с единичным ребром точки M, N, P, Q, Т заданы равенствами \bar{BM}=2\bar{MA},...

Векторное произведение
Доброго времени суток! Есть пара вопросов:) -&gt; Пусть есть вектор а с координатами {x1, y1, z1} и...

Векторное произведение
Помогите пожалуйста решить векторное произведение векторов на php. Задали, и только 2 лекции были...

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


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

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

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