Быстрая обработка матриц

Тема в разделе "LANGS.C", создана пользователем ring4, 20 фев 2011.

  1. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    Имеется кусок кода который выполняется почти 1 секунду:

    Код (Text):
    1. const int size = 500;
    2. static double F[size][size];
    3. static double tm[size][size];
    4. for(m=0; m<size; m++)
    5. {
    6. /// немного кода
    7. //вот собственно отсюда и идет весь провал времени.
    8. //можно ли как нить оптимизировать работу с массивом
    9. //ибо слишком много времени тратится на присвоение вычисленного значения в массив
    10. for( q = 0; q<size; q++)
    11.             {
    12.                 tm[0][q] +=F[m][q]*t;
    13.             }
    14. }
     
  2. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    tm[0][q] заменить локальной переменной.
    Использовать указатели.
    Сделать раскрутку цикла.
    Использовать операции над упакованными данными(инстрикси и другие расширения).
     
  3. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    Pavia
    Спасибо много новых слов узнал, буду разбираться)
     
  4. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    подключил компилятором раскрутку циклов, задействовал sse. но мне вот что не дает покоя:

    double temp = tm[q]+F[m][q]*2;
    double ttl = 0.447384;
    tm[q] = temp; // or ttl

    в переменной temp значение порядка равного ttl. но вот присвоение ttl проходит за 0.25 секунд, а temp при 0.8. Не могу понять почему такое происходит?
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Что-то у вас странное происходит.
    Код (Text):
    1. #include <iostream>
    2. #include <windows.h>
    3.  
    4. const int size = 500;
    5. static double F[size][size];
    6. static double tm[size][size];
    7.  
    8. int main (int argc, char* argv[])
    9. {
    10.     LARGE_INTEGER frequency;
    11.     bool bHpet = QueryPerformanceFrequency(&frequency);
    12.     std::cout<<"HPET = "<<std::boolalpha<<bHpet<<std::endl;
    13.     LARGE_INTEGER counterStart;
    14.     QueryPerformanceCounter(&counterStart);
    15.     const int t = 2;
    16.     for(int m=0; m<size; m++)
    17.     {
    18.         for(int q = 0; q<size; q++)
    19.         {
    20.             tm[0][q] +=F[m][q]*t;
    21.         }
    22.     }
    23.     LARGE_INTEGER counterEnd;
    24.     QueryPerformanceCounter(&counterEnd);
    25.     double time = (double(counterEnd.QuadPart - counterStart.QuadPart)) / (double)frequency.QuadPart;
    26.     std::cout<<"time = "<<time<<"sec."<<std::endl;
    27. }
    time = 0.0025seс.
     
  6. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    меж коментариев затерялось:
    Код (Text):
    1.     for(int m=0; m<size; m++)
    2.     {
    3.       for(int i=0; i<size; i++)
    4.        {
    5.           for(int q = 0; q<size; q++)
    6.          {
    7.                tm[0][q] +=F[m][q]*t;
    8.          }
    9.        }
    10.     }
    for(int i=0; i<size; i++) -- вот тута и проблема во времени. непомню откуда оно взялось. щас буду проверять
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Тонкая шутка. Вначале действительно нужно разобраться с алгоритмом. ^)
     
  8. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Выкинуть цикл, заменить умножением.
     
  9. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    Pavia Booster
    Возможно не все так просто) или наоборот

    Код (Text):
    1. #include <iostream>
    2. #include <windows.h>
    3. #include <ctime>
    4.  
    5. const int size = 500;
    6. static float A[size][size];
    7. static float b[size][size];
    8. static float F[size][size];
    9. static float tm[size][size];
    10.  
    11. using namespace std;
    12.  
    13. int main ()
    14. {
    15.     //генерация матриц
    16.     int e = rand();
    17.     for(int p=0;p<size;p++)
    18.     {
    19.        
    20.         b[p][0] = e;
    21.         for(int j=0; j<size; j++)
    22.         {
    23.             int h = rand();
    24.             A[p][j]=h;
    25.             if(p == j)
    26.             {
    27.                 F[p][j] =1;
    28.             }else
    29.             {
    30.                 F[p][j] = 0;
    31.             }
    32.         }
    33.     }
    34.  
    35.     //засекаем время выполения
    36.     clock_t tStart;
    37.     tStart = clock();
    38.     int m,i;
    39.  
    40.     for(m=0; m<size; m++)
    41.     {
    42.         for(i=0; i<size; i++)
    43.         {
    44.             //проверка первого условия
    45.             if(i+1 != m+1)
    46.             {
    47.             //выполнение второго условия
    48.             float t1=0,t2=0;
    49.  
    50.             //разбиваем действие на поддействия, находим отдельно числитель и знаменатель,
    51.             //потом обрабатываем
    52.             for(int k = 0; k<size; k++)
    53.             {
    54.                 t1 += F[i][k]*A[k][m];
    55.                 t2 += F[m][k]*A[k][m];
    56.             }
    57.    
    58.             double t = t1/t2;
    59.             int fpc = _fpclass(t);
    60.             switch(fpc)
    61.             {
    62.                  case    _FPCLASS_QNAN:
    63.                     t=0;
    64.                     break;
    65.                 case    _FPCLASS_NINF:
    66.                     t=0;
    67.                     break;
    68.                 case    _FPCLASS_PINF:
    69.                     t=0;
    70.                     break;
    71.             }
    72.  
    73.         //  cout << t << "\n";
    74.             for(int q = 0; q<size; q++)
    75.             {
    76.                 tm[0][q] = tm[0][q]+(F[m][q])*(t);
    77.             }
    78.  
    79.             for(int w = 0; w<size; w++)
    80.             {
    81.                 F[i][w] = F[i][w] - tm[0][w];
    82.             }
    83.  
    84.             }
    85.         }
    86.     }
    87.     cout << (float)(clock() - tStart) / CLOCKS_PER_SEC << "\n";
    88.  
    89.     return 0;
    90. }
    так вот прикол начинается с того что если t вычисляется как t1/t2 то время порядка 1 секунды, если t поставить любое число то время снижается до 0.2 не мойму как оно может влиять.
    Алгоритм работает верно, это какаято модификация решения слау, писал когдато по алгоритму предложенным преподавателем в универе.

    щас подумаю как выкинуть цикл можно, но не думаю что получится
     
  10. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Думаю для начало нужно хотя-бы разобраться, что это за метод решения и затем переписать в более читабельный вид.
     
  11. artkar

    artkar New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2005
    Сообщения:
    400
    Адрес:
    Russia
    Код (Text):
    1. double*p=F;// Взяли указатель на начало массива(адрес 1-го элемента)
    2. int q=0;
    3. int length = size*size;
    4.  
    5. for(int i=0 ; i<length ; i++, q++)
    6. {
    7.   if (q>(size-1)) q=0;
    8.   tm[0][q] += ((*p++)*size)*t;
    9. };
    Идея в следующем: если ты объявляешь статический массив как F[size][size], тогда все значения в нём содержаться последовательно и можно обойтись одинарным циклом для обхода двухмерного массива.

    Цикл for(int i=0; i<size; i++) не нужен, он заменяется умножением на size, если я правильно понял алго

    Код писал без компилятора, на память, так что надо проверять.
     
  12. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    artkar
    понятно, попробую завтра, но всетаки непонятно почему при постоянной и переменной t меняется время.
     
  13. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    ring4
    У меня ваш код выполняется очень долго.

    Оптимизация. Этот кусок компилятор может вообще выбросить.
    Код (Text):
    1. for(int k = 0; k<size; k++)
    2. {
    3.      t1 += F[i][k]*A[k][m];
    4.      t2 += F[m][k]*A[k][m];
    5. }
    И почему бы эти два цикла не объединить в один?
    Код (Text):
    1. for(int q = 0; q<size; q++)
    2. {
    3.    tm[0][q] = tm[0][q]+(F[m][q])*(t);
    4. }
    5.  
    6. for(int w = 0; w<size; w++)
    7. {
    8.      F[i][w] = F[i][w] - tm[0][w];
    9. }
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Ещё это улыбнуло:
    Код (Text):
    1. if(i+1 != m+1)
    Почему не if(i != m)?
     
  15. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    Booster
    честно писал давно,да побыстрей чтобы сдать работу, а щас данный метод пригодился в реальной жизни.
    А не льзя объеденить т.к это реализация формулы и там сначала нужно все просумировать. щас попробую написать формулу если интересно, это модификация метода исключения гауса.
     
  16. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    вот то что соответствует коду: http://--------- не не то, здесь какаято модификация модификации) лучше завтра на трезвую голову подумаю
     
  17. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    ring4
    По-моему можно, так как суммируется по разными рядам - if(i != m).

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

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    gpu попробую, но для начала планирую всетаки написать нормальный "линейный" код а потом распаралелить его. проц. 30% производительности для 2 ядреных систем должно быть. а там видно будет. ну для gpu я думаю должна быть нормальная видюха, а тут более вероятно что многоядерный проц быстрее будет, чем топовая видео карта
     
  19. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Не может такого быть по определению. Даже не топ видеокарты уделывают процы в сотни раз.
     
  20. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    это просто ЛОЛ, с БОЛЬШОЙ БУКВЫ ЛОЛ. Мой 4х ядерный квадр, просто отдыхает по сравнению с моей GTS 250, а она давно не топ. Причем отдыхает, раз так в 10-15 минимум.