2013-05-08 2 views
2

Я пытаюсь оптимизировать closest pair brute force algorithm и сравнивать его с не кэшированной программой, но я застрял.Реализация метода кэширования в алгоритме ближайших пар

Основная проблема заключается в том, что я получаю худшую производительность, когда я кэширую вычисления с помощью циклов for, почти cached time = 2 x non-cached time. Его как будто ничего не происходит, если я изменить размер блока ... Я использую точку массива структура Р для х, у cordinates

Вот без кеширования код:

void compare_points_BF(int *N, point *P){ 
    int i, j, p1, p2; 
    float dx, dy, distance=0, min_dist=inf(); 
    long calc = 0; 

    for (i=0; i<(*N-1) ; i++){ 
     for (j=i+1; j<*N; j++){ 
      dx = P[i].x - P[j].x; 
      dy = P[i].y - P[j].y; 
      //calculate distance of current points 
      distance = (dx * dx) + (dy * dy); 
      calc++; 
      if (distance < min_dist){ 
       min_dist = distance; 
       p1 = i; 
       p2 = j; 
      } 
     } 
    } 
    printf("%ld calculations\t", calc); 
} 

И вот кэшируются версия:

void compare_points_BF(int *N, int *B, point *P){ 
     int i, j, ib, jb, p1, p2, num_blocks = (*N + (*B-1))/(*B); 
     float dist=0, min_dist=inf(); 
     long calc=0; 

     //break array data in N/B blocks 
     for (i = 0; i < num_blocks; i++){ 
      for (j = i; j < num_blocks; j++){ 
       for (jb = j * (*B); jb < min((j+1) * (*B), *N); jb++){ 
        //avoid double comparisons that occur when i block = j block 
        for (i == j ? (ib = jb + 1) : (ib = i*(*B)); ib < min((i+1) * (*B), *N); ib++){ 
         calc++; 
         //calculate distance of current points 
         if((dist = (P[ib].x - P[jb].x) * (P[ib].x - P[jb].x) + 
           (P[ib].y - P[jb].y) * (P[ib].y - P[jb].y)) < min_dist){ 
          min_dist = dist; 
          p1 = ib; 
          p2 = jb; 
         } 
        } 
       } 
      } 
     } 
     printf("%ld calculations\t", calc); 
} 

Например выход некэшируемых программ:

N = 8192  Run time: 0,080 sec 
N = 16384 Run time: 0,330 sec 
N = 32768 Run time: 1,280 sec 
N = 65.536 Run time: 5,290 sec 
N = 131.072 Run time: 21,290sec 
N = 262.144 Run time: 81,880sec 
N = 524.288 Run time: 327,460 sec 

Но с КК hed пример:

33550336 calculations Block_size = 128 N = 8192 Run time: 0.402 sec 
33550336 calculations Block_size = 256 N = 8192 Run time: 0.383 sec 
33550336 calculations Block_size = 512 N = 8192 Run time: 0.384 sec 
33550336 calculations Block_size = 1024 N = 8192 Run time: 0.381 sec 
33550336 calculations Block_size = 2048 N = 8192 Run time: 0.398 sec 
33550336 calculations Block_size = 4096 N = 8192 Run time: 0.400 sec 
33550336 calculations Block_size = 8192 N = 8192 Run time: 0.401 sec 
33550336 calculations Block_size = 16384 N = 8192 Run time: 0.383 sec 

134209536 calculations Block_size = 128 N = 16384 Run time: 1.579 sec 
134209536 calculations Block_size = 256 N = 16384 Run time: 1.610 sec 
134209536 calculations Block_size = 512 N = 16384 Run time: 1.630 sec 
134209536 calculations Block_size = 1024 N = 16384 Run time: 1.530 sec 
134209536 calculations Block_size = 2048 N = 16384 Run time: 1.537 sec 
134209536 calculations Block_size = 4096 N = 16384 Run time: 1.562 sec 
134209536 calculations Block_size = 8192 N = 16384 Run time: 1.520 sec 
134209536 calculations Block_size = 16384 N = 16384 Run time: 1.626 sec 

536854528 calculations Block_size = 128 N = 32768 Run time: 6.170 sec 
536854528 calculations Block_size = 256 N = 32768 Run time: 6.207 sec 
536854528 calculations Block_size = 512 N = 32768 Run time: 6.219 sec 
536854528 calculations Block_size = 1024 N = 32768 Run time: 6.131 sec 
536854528 calculations Block_size = 2048 N = 32768 Run time: 6.077 sec 
536854528 calculations Block_size = 4096 N = 32768 Run time: 6.216 sec 
536854528 calculations Block_size = 8192 N = 32768 Run time: 6.130 sec 
536854528 calculations Block_size = 16384 N = 32768 Run time: 6.181 sec 

Я проверял код заново, и это кажется правильным. Что мне здесь не хватает? Компилятор оптимизирует код для реализации лучшего использования кеша, чем я пытаюсь достичь? Спасибо заранее!

+0

Четыре вложенных цикла по сравнению с двумя, и, похоже, больше выражений для оценки в вашей «кешированной» версии. Нет, это не будет быстрее. –

+0

@JoachimPileborg Но как я должен ломать данные в блоках, не используя дополнительные для циклов? Хотя, вычисления одинаковы. – BugShotGG

+0

Вы считаете количество вложенных циклов как «вычисление», но в вашей «кешированной» версии есть еще много выражений. Ваша «нераскрытая» версия проста, простая часто бывает хорошей. И даже если вам удастся сжать на один или два процента лучшее время исполнения, часто это делается с усложнением алгоритмов и, следовательно, гораздо труднее понять. –

ответ

1

Был долгим, но только для ответа на вопрос.

float compare_points_BF(register int N, register int B, point *P, register point *p1, *p2;){ 

register int i, j, ib, jb, iin, jjn, num_blocks = (N + (B-1))/B; 
register float distance=0, min_dist=FLT_MAX, regx, regy; 

    //break array data in N/B blocks 
    for (i = 0; i < num_blocks; i++){ 
     for (j = i; j < num_blocks; j++){ 
      iin = (((i+1)*B) < N ? ((i+1)*B) : N); 
      jjn = (((j+1)*B) < N ? ((j+1)*B) : N); 
      //reads the moving frame block to compare with the i block 
      for (jb = j * B; jb < jjn; jb++){ 
      //avoid float comparisons that occur when i block = j block 
      //Registers Allocated 
      regx = P[jb].x; 
      regy = P[jb].y; 
      for (i==j ? (ib=jb+1):(ib=i*B); ib < iin; ib++){ 
       //calculate distance of current points 
       if((distance = (P[ib].x - regx) * (P[ib].x - regx) + 
         (P[ib].y - regy) * (P[ib].y - regy)) < min_dist){ 
       min_dist = distance; 
       p1 = &P[ib]; 
       p2 = &P[jb]; 
       } 
      } 
      } 
     } 
    } 
    return sqrt(min_dist); 
} 

Это использование кэш-памяти позволяет увеличить скорость до 10%. Вот некоторые результаты.

Block 
Size Number of elements 
     8192 16384 32768 65536 131072 262144 524288 1048576 
128  0,079 0,310 1,260 4,960 19,740 78,990 315,661 1.260,862 
256  0,079 0,310 1,250 4,940 19,830 78,820 315,410 1.258,402 
512  0,080 0,320 1,260 4,920 19,640 78,480 313,851 1.253,141 
1024 0,080 0,320 1,250 4,870 19,430 77,540 310,120 1.237,772 
2048 0,079 0,310 1,240 4,850 19,340 77,061 308,211 1.229,892 
4096 0,079 0,300 1,210 4,890 19,670 78,300 313,310 1.250,572 
8192 0,078 0,310 1,210 4,870 19,510 78,110 312,770 1.249,091 
16384   0,300 1,200 4,860 19,420 77,870 312,151 1.246,192 
32768     1,190 4,780 19,310 77,460 310,970 1.242,102 
65536       4,760 19,230 77,660 312,191 1.249,872 
131072         18,972 76,850 310,470 1.246,261 
262144           76,400 307,521 1.239,402 

 Смежные вопросы

  • Нет связанных вопросов^_^