улучшить локальность и уменьшить загрязнение кеша в реализация реконструкции медицинских изображений

I ' Я провожу исследование для моего университета, связанное с алгоритмом реконструкции изображений для использования в медицине.

Я застрял в чем-то на 3 недели, мне нужно улучшить производительность следующего кода:

for (lor=lor0[mypid]; lor <= lor1[mypid]; lor++)
{
  LOR_X = P.symmLOR[lor].x;
  LOR_Y = P.symmLOR[lor].y;
  LOR_XY = P.symmLOR[lor].xy;
  lor_z = P.symmLOR[lor].z;
  LOR_Z_X = P.symmLOR[lor_z].x;
  LOR_Z_Y = P.symmLOR[lor_z].y;
  LOR_Z_XY = P.symmLOR[lor_z].xy;  

  s0 = P.a2r[lor];
  s1 = P.a2r[lor+1];

  for (s=s0; s < s1; s++)
  {
    pixel     = P.a2b[s];
    v         = P.a2p[s]; 

    b[lor]    += v * x[pixel];

    p          = P.symm_Xpixel[pixel];
    b[LOR_X]  += v * x[p];

    p          = P.symm_Ypixel[pixel];
    b[LOR_Y]  += v * x[p];

    p          = P.symm_XYpixel[pixel];
    b[LOR_XY] += v * x[p];


    // do Z symmetry.
    pixel_z    = P.symm_Zpixel[pixel];
    b[lor_z]  += v * x[pixel_z];


    p          = P.symm_Xpixel[pixel_z];
    b[LOR_Z_X]  += v * x[p];


    p          = P.symm_Ypixel[pixel_z];
    b[LOR_Z_Y]  += v * x[p];

    p          = P.symm_XYpixel[pixel_z];
    b[LOR_Z_XY] += v * x[p];

   }

}

для всех, кто хочет знать, Код реализует функцию пересылки MLEM и все переменные FLOAT .

После нескольких тестов я заметил, что в этой части кода была большая задержка. (вы знаете, правило 90 - 10).

Позже я использовал Papi (http://cl.cs.utk.edu/papi/) для измерения промахов кэша L1D. Как я и думал, Папи подтверждают, что производительность снижается из-за большего количества промахов, особенно для произвольного доступа к вектору b (огромного размера).

Читая информацию в Интернете, я знаю только два варианта повышения производительности: улучшить локальность данных или уменьшить загрязнение данных.

Чтобы сделать первое улучшение, я попытаюсь изменить код, чтобы он учитывал кэш, как это было предложено Ульрихом Дреппером в Что каждый программист должен знать о памяти (www.akkadia.org /drepper/cpumemory.pdf) A.1 Умножение матриц.

Я считаю, что блокирование SpMV (разреженное умножение матрицы на вектор) улучшит производительность.

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

Есть ли способ загрузить значение из вектора b с помощью инструкции SIMD без использования кеша?

Кроме того, можно использовать такую ​​функцию, как void _mm_stream_ps (float * p, __m128 a) для хранения ОДНО значение с плавающей запятой в векторе b, не загрязняя кеш?

Я могу ' t используйте _mm_stream_ps, потому что всегда храните 4 числа с плавающей запятой, но доступ к вектору b явно случайный.

Я надеюсь, что моя дилемма будет ясна.

Дополнительная информация: v - значение столбца в хранилище разреженной матрицы с Формат CRS. Я понимаю, что можно было бы выполнить другую оптимизацию, если бы я попытался изменить формат CRS на другой, однако, как я уже говорил, я провел несколько тестов в течение месяцев и знаю, что снижение производительности связано с произвольным доступом к вектору b. от 400.000.000 промахов L1D Я могу перейти к 100 ~ промахам, если не сохраняю в векторе b.

Спасибо.

5
задан Fbarisio 18 January 2011 в 21:50
поделиться