Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.93
iltat
0 / 0 / 0
Регистрация: 15.05.2014
Сообщений: 17
#1

Программирование под GPU: Вычисление произведения матрицы на вектор - C++

15.05.2014, 14:56. Просмотров 2480. Ответов 32
Метки нет (Все метки)

Доброго времени суток!Ветку, связанную с программированием на ГПУ не нашел, пишу сюда.
проблема следующая. Есть код на С++ под ЦПУ и код на С++ под ГПУ для вычисления произведения матрицы на вектор.
По идее на ГПУ вычисления должны распараллеливаться, но возникает ситуация такая, что код, вычисляемын на ЦПУ работает быстрее. С чем бы это связано. В качестве библиотеки по ГПУ использовал CUDA и C++ AMP.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.05.2014, 14:56
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Программирование под GPU: Вычисление произведения матрицы на вектор (C++):

Сформировать вектор B, компонентами которого являются произведения отрицательных элементов строк матрицы A - C++
Дана матрица A размерности N*N Сформировать вектор B(N), компонентами которого являются произведения отрицательных элементов строк...

Вычисление суммы и произведения элементов матрицы, находящихся на главной диагонали - C++
Задана квадратная матрица размером к на к, составить программу вычисления суммы и произведения элементов матрицы, находящихся на главной...

Вычисление степени матрицы, вычисления произведения двух матриц, вычисление суммы двух матриц - C++
Здравствуйте, помогите решить, пожалуйста: Заданы две квадратные матрицы А и В. Вычислить матрицу...

Рассматривая каждую строку прямоугольной матрицы как вектор, найти номера векторов-строк, для которых модуль их скалярного произведения S имеет максим - C++
Рассматривая каждую строку прямоугольной матрицы как вектор, найти номера векторов-строк, для которых модуль их скалярного произведения S...

Матрицы. Получить вектор X, равный P-й строке матрицы, и вектор Y, равный Q-му столбцу матрицы - C++
1. Дана матрица A (3 х 5). Получить вектор X, равный P-й строке матрицы, и вектор Y, равный Q-му столбцу матрицы. P и Q запросить у...

Найти разность произведения нечетных чисел 3-ей строки и произведения отрицательных чисел 1-го столбца матрицы - C++
Найти разность произведения нечетных чисел 3-ей строки и произведения отрицательных чисел 1-го столбца матрицы В(4,4).

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
nmcf
5319 / 4639 / 1551
Регистрация: 14.04.2014
Сообщений: 18,452
15.05.2014, 15:02 #2
Тексты программ-то где? Как ты определил, что там быстрее?
0
Kuzia domovenok
1891 / 1746 / 118
Регистрация: 25.03.2012
Сообщений: 5,925
Записей в блоге: 1
15.05.2014, 15:36 #3
iltat, телепаты в отпуске. Как тестил? чем измерял время? Может ты там матрицы 2 на 2 перемножаешь, и естесственно больше времени уходит на то, чтобы загрузить/выгрузить их в видюху, чем на сами вычисления?
0
iltat
0 / 0 / 0
Регистрация: 15.05.2014
Сообщений: 17
15.05.2014, 18:25  [ТС] #4
у меня и матрица и вектор задается в виде одномерного массива.
Код:
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
int getRazm(int kolQbs){
        int rzm=1;
        for(int i=0;i<kolQbs;i++){
            rzm=rzm*2;
        }
        return rzm;
    }
void getAnyMatrMV(float* matr,float* vctrRe1,float* vctrIm1,int kolQbs){
        int rzm=getRazm(kolQbs);
        DWORD xxx=GetTickCount();
        array_view<float,1> x(rzm,vctrRe1);
        array_view<float,1> x1(rzm,vctrIm1);
        float* vctRtrnRe=new float[rzm];
        float* vctRtrnIm=new float[rzm];
        array_view<float,1> y(rzm,vctRtrnRe);
        array_view<float,1> y1(rzm,vctRtrnIm);
        array_view<float,1> mrc(rzm*rzm,matr);
        //concurrency::extent<1> e(rzm);
        //mrc.discard_data();
        parallel_for_each(mrc.extent, [=](index<1> i) restrict(amp)
        {
            float res=0,res1=0;
            for(int k = 0; k < rzm; k++)
            {
            res+=x(k)*mrc(i*rzm+k);
            res1+=x1(k)*mrc(i*rzm+k);
            }
            y(i)=res;
            y1(i)=res1;
        });
        y.synchronize();
        y1.synchronize();
        y.copy_to(x);
        y1.copy_to(x1);
        DWORD yyy=GetTickCount();
        cout<<yyy-xxx<<endl;
        //getTOG(vctRtrnRe,vctRtrnIm,vctrRe1,vctrIm1,rzm);
    }
getAnyMatrM(float* matr,float* vctrRe1,float* vctrIm1,int kolQbs){
        int rzm=getRazm(kolQbs);
                DWORD xxx=GetTickCount();               
int j=0;
        int k=0;
        float*vctrRe=new float[rzm];
        vctrRe[0]=0;
        float*vctrIm=new float[rzm];
        vctrIm[0]=0;
        
        for(int i=0;i<rzm*rzm;i++){
            vctrRe[j]=vctrRe[j]+vctrRe1[k]*matr[i];
            vctrIm[j]=vctrIm[j]+vctrIm1[k]*matr[i];
            
            if((i+1)%rzm!=0){
                k++;
            }else{
                j++;k=0;
                if(j<rzm){
                    vctrRe[j]=0;
                    vctrIm[j]=0;
                }
            }
        }
        for(int i=0;i<rzm;i++){
            vctrRe1[i]=vctrRe[i];
            vctrIm1[i]=vctrIm[i];
        }
DWORD yyy=GetTickCount();
        cout<<yyy-xxx<<endl;
    }
 
int _tmain(int argc, _TCHAR* argv[])
{
    int st=10;
    int N=getRazm(st);
    float*vcIm=new float[N];
    float*vcRe=new float[N];
    float*matr=new float[N*N];
    for(int i=0;i<N;i++){
        vcRe[i]=i;
        vcIm[i]=i;
        for(int j=0;j<N;j++){
            matr[i*N+j]=i;
        }
    }
    getAnyMatrM(matr,vcRe,vcIm,st);
    getAnyMatrMV(matr,vcRe,vcIm,st);
    int x;
    cin>>x;
    return 0;
    
}
0
iltat
0 / 0 / 0
Регистрация: 15.05.2014
Сообщений: 17
17.05.2014, 00:06  [ТС] #5
у меня и матрица и вектор задается в виде одномерного массива, код выше
0
iltat
0 / 0 / 0
Регистрация: 15.05.2014
Сообщений: 17
20.05.2014, 17:20  [ТС] #6
Kuzia domovenok, у меня и матрица и вектор задается в виде одномерного массива, код выше

Добавлено через 15 секунд
nmcf, у меня и матрица и вектор задается в виде одномерного массива, код выше
0
newbie666
Заблокирован
20.05.2014, 17:27 #7
1. где код на CUDA?
2. Чтобы умножить одну матрицу на вектор - использовать GPU - глупо. Вот если у тебя миллионы этих матриц...

Всё зависит от кривости рук прогера, ты можешь на GPU такой код написать, что он у тебя будет в сотни раз медленней, чем на CPU... Там куча нюансов... Memory Coalescing, выравнивания прочие и тд
0
iltat
0 / 0 / 0
Регистрация: 15.05.2014
Сообщений: 17
20.05.2014, 17:48  [ТС] #8
newbie666, а если матрица млн на млн?
0
newbie666
Заблокирован
20.05.2014, 20:49 #9
Цитата Сообщение от iltat Посмотреть сообщение
а если матрица млн на млн?
тогда есть смысл на GPU выполнять.
Так где твой код - то то GPU? Какой у тебя GPU?
Ставь на Visual Studi 2012 сверху NVIDIA Nsight Visual Studio Edition и сотри егошним профайлером на то, где у тебя основные тормоза и из - за чего.
А если у тебя крутой Kepler GPU на крутой железе типа Quadro или Telsa - то сможешь ещё и SMX процессоры отлаживать в реальном времени

Добавлено через 2 часа 48 минут
Цитата Сообщение от iltat Посмотреть сообщение
а если матрица млн на млн
да кстате, если у тебя матрица миллион на миллион и в каждой ячейке хотя бы простой Int, то тебе потребуется 3,63 террабайта видео памяти для заливания матрицы на GPU
Или хотя бы столько же обычной RAM, чтоб оттуда копировать частями на GPU
0
iltat
0 / 0 / 0
Регистрация: 15.05.2014
Сообщений: 17
20.05.2014, 21:12  [ТС] #10
newbie666, я выполнял на C++ AMP:
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
void getAnyMatrMV(float* matr,float* vctrRe1,float* vctrIm1,int kolQbs){
        int rzm=getRazm(kolQbs);
        DWORD xxx=GetTickCount();
        array_view<float,1> x(rzm,vctrRe1);
        array_view<float,1> x1(rzm,vctrIm1);
        float* vctRtrnRe=new float[rzm];
        float* vctRtrnIm=new float[rzm];
        array_view<float,1> y(rzm,vctRtrnRe);
        array_view<float,1> y1(rzm,vctRtrnIm);
        array_view<float,1> mrc(rzm*rzm,matr);
        //concurrency::extent<1> e(rzm);
        //mrc.discard_data();
        parallel_for_each(mrc.extent, [=](index<1> i) restrict(amp)
        {
            float res=0,res1=0;
            for(int k = 0; k < rzm; k++)
            {
            res+=x(k)*mrc(i*rzm+k);
            res1+=x1(k)*mrc(i*rzm+k);
            }
            y(i)=res;
            y1(i)=res1;
        });
        y.synchronize();
        y1.synchronize();
        y.copy_to(x);
        y1.copy_to(x1);
        DWORD yyy=GetTickCount();
        cout<<yyy-xxx<<endl;
        //getTOG(vctRtrnRe,vctRtrnIm,vctrRe1,vctrIm1,rzm);
    }
Добавлено через 1 минуту
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
extern "C" __declspec(dllexport) __global__ void MatrVectMul(float *re,float* im, float *matr,int rzm)
{
    int i = blockIdx.x*blockDim.x+threadIdx.x;
    float sum,sum1;
    if(i<rzm)
    {
    sum=0,sum1=0;
    for (int k=0;k<rzm && i<rzm;k++){
        sum+=matr[i*rzm+k]*re[k];
        sum1+=matr[i*rzm+k]*im[k];
    }
    re[i]=sum;
    im[i]=sum1;
    }
}
Это код на CUDA
0
newbie666
Заблокирован
20.05.2014, 21:16 #11
покажи две свои функции, выполняющие ОДИНАКОВЫЕ действия, на CPU и на GPU
0
iltat
0 / 0 / 0
Регистрация: 15.05.2014
Сообщений: 17
20.05.2014, 21:17  [ТС] #12
Здесь происходит вызов этого кода
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
extern "C" __declspec(dllexport) void getAnyMatrM(float *vctrRe,float *vctrIm, float *matr,int rzm){
    float *vctrReV,*vctrImV,*matrV;
    // выделение видеопамяти
    cudaMalloc((void **)&vctrReV, sizeof(int)*rzm);
    cudaMalloc((void **)&vctrImV, sizeof(int)*rzm); 
    cudaMalloc((void **)&matrV, sizeof(int)*rzm*rzm);
// копирование из оперативной памяти в видеопамять
    cudaMemcpy(vctrReV, vctrRe, sizeof(int)*rzm, cudaMemcpyHostToDevice);
    cudaMemcpy(vctrImV, vctrIm, sizeof(int)*rzm, cudaMemcpyHostToDevice);
    cudaMemcpy(matrV, matr, sizeof(int)*rzm*rzm, cudaMemcpyHostToDevice);
    // установка количества блоков
    dim3 grid((rzm+255)/256, 1, 1);
    // установка количества потоков в блоке
    dim3 threads(256, 1, 1);
    MatrVectMul<<< grid,threads>>> (vctrReV,vctrImV,matrV,rzm);
    //Синхронизируем с моментом окончания расчетов
    cudaMemcpy(vctrRe, vctrReV, sizeof(int)*rzm, cudaMemcpyDeviceToHost);
    cudaMemcpy(vctrIm, vctrImV, sizeof(int)*rzm, cudaMemcpyDeviceToHost);
    // освобождение памяти
    cudaFree(vctrReV);
    cudaFree(vctrImV);
}
0
newbie666
Заблокирован
20.05.2014, 21:20 #13
Цитата Сообщение от newbie666 Посмотреть сообщение
покажи две свои функции, выполняющие ОДИНАКОВЫЕ действия, на CPU и на GPU
0
iltat
0 / 0 / 0
Регистрация: 15.05.2014
Сообщений: 17
20.05.2014, 21:21  [ТС] #14
newbie666,
Вот ГПУ
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
 void getAnyMatrMV(float* matr,float* vctrRe1,float* vctrIm1,int kolQbs){
        int rzm=getRazm(kolQbs);
        DWORD xxx=GetTickCount();
        array_view<float,1> x(rzm,vctrRe1);
        array_view<float,1> x1(rzm,vctrIm1);
        float* vctRtrnRe=new float[rzm];
        float* vctRtrnIm=new float[rzm];
        array_view<float,1> y(rzm,vctRtrnRe);
        array_view<float,1> y1(rzm,vctRtrnIm);
        array_view<float,1> mrc(rzm*rzm,matr);
        //concurrency::extent<1> e(rzm);
        //mrc.discard_data();
        parallel_for_each(mrc.extent, [=](index<1> i) restrict(amp)
        {
            float res=0,res1=0;
            for(int k = 0; k < rzm; k++)
            {
            res+=x(k)*mrc(i*rzm+k);
            res1+=x1(k)*mrc(i*rzm+k);
            }
            y(i)=res;
            y1(i)=res1;
        });
        y.synchronize();
        y1.synchronize();
        y.copy_to(x);
        y1.copy_to(x1);
        DWORD yyy=GetTickCount();
        cout<<yyy-xxx<<endl;
        //getTOG(vctRtrnRe,vctRtrnIm,vctrRe1,vctrIm1,rzm);
    }
Вот ЦПУ:
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
getAnyMatrM(float* matr,float* vctrRe1,float* vctrIm1,int kolQbs){
        int rzm=getRazm(kolQbs);
                DWORD xxx=GetTickCount();               
int j=0;
        int k=0;
        float*vctrRe=new float[rzm];
        vctrRe[0]=0;
        float*vctrIm=new float[rzm];
        vctrIm[0]=0;
        
        for(int i=0;i<rzm*rzm;i++){
            vctrRe[j]=vctrRe[j]+vctrRe1[k]*matr[i];
            vctrIm[j]=vctrIm[j]+vctrIm1[k]*matr[i];
            
            if((i+1)%rzm!=0){
                k++;
            }else{
                j++;k=0;
                if(j<rzm){
                    vctrRe[j]=0;
                    vctrIm[j]=0;
                }
            }
        }
        for(int i=0;i<rzm;i++){
            vctrRe1[i]=vctrRe[i];
            vctrIm1[i]=vctrIm[i];
        }
DWORD yyy=GetTickCount();
        cout<<yyy-xxx<<endl;
    }
Добавлено через 57 секунд
И вот CUDA
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
extern "C" __declspec(dllexport) __global__ void MatrVectMul(float *re,float* im, float *matr,int rzm)
{
    int i = blockIdx.x*blockDim.x+threadIdx.x;
    float sum,sum1;
    if(i<rzm)
    {
    sum=0,sum1=0;
    for (int k=0;k<rzm && i<rzm;k++){
        sum+=matr[i*rzm+k]*re[k];
        sum1+=matr[i*rzm+k]*im[k];
    }
    re[i]=sum;
    im[i]=sum1;
    }
}
extern "C" __declspec(dllexport) void getAnyMatrM(float *vctrRe,float *vctrIm, float *matr,int rzm){
    float *vctrReV,*vctrImV,*matrV;
    // выделение видеопамяти
    cudaMalloc((void **)&vctrReV, sizeof(int)*rzm);
    cudaMalloc((void **)&vctrImV, sizeof(int)*rzm); 
    cudaMalloc((void **)&matrV, sizeof(int)*rzm*rzm);
// копирование из оперативной памяти в видеопамять
    cudaMemcpy(vctrReV, vctrRe, sizeof(int)*rzm, cudaMemcpyHostToDevice);
    cudaMemcpy(vctrImV, vctrIm, sizeof(int)*rzm, cudaMemcpyHostToDevice);
    cudaMemcpy(matrV, matr, sizeof(int)*rzm*rzm, cudaMemcpyHostToDevice);
    // установка количества блоков
    dim3 grid((rzm+255)/256, 1, 1);
    // установка количества потоков в блоке
    dim3 threads(256, 1, 1);
    MatrVectMul<<< grid,threads>>> (vctrReV,vctrImV,matrV,rzm);
    //Синхронизируем с моментом окончания расчетов
    cudaMemcpy(vctrRe, vctrReV, sizeof(int)*rzm, cudaMemcpyDeviceToHost);
    cudaMemcpy(vctrIm, vctrImV, sizeof(int)*rzm, cudaMemcpyDeviceToHost);
    // освобождение памяти
    cudaFree(vctrReV);
    cudaFree(vctrImV);
}
0
newbie666
Заблокирован
20.05.2014, 21:32 #15
Покажи код двух функций, которые делают одно и тоже, но одна делает на GPU, другая на CPU. Нужно показать те функции, где на GPU у тебя медленнее выполняется, чем на CPU. Так же нужно сообщить, какой у тебя CPU и какой GPU
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.05.2014, 21:32
Привет! Вот еще темы с ответами:

Вычисление произведения - C++
Доброго время суток. Написать программу вычисления произведения: \prod_{1}^{\propto}\cos(\frac{\pi }{{2}^{(n+1)}}) = \frac{2}{\pi } ...

Вычисление произведения - C++
Здравствуйте. Мне проблема в том, что я не знаю как написать код по данным примерам. Не могли бы вы помочь, и скинуть литературу. ...

Вычисление произведения сумм - C++
t=\prod_{a=1}^{5}\sum_{b=1}^{10}cos\,ab Помогите пожалуйста я не очень знаю с++ буду благодарен

Вычисление конечного произведения - C++
Всем Доброго времени суток! Имеется задача: Вычислить произведение \sum_{n=1}^{k} (1+\frac{x^n}{2n!}) Я сделал данную программу, заведя...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
20.05.2014, 21:32
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru