OpenCl: добавление большого количества массивов

В приведенном ниже коде каждый рабочий элемент генерирует массив sum_qcos_i.
Чтобы добавить их, я сначала делаю локальное сложение, используя локальный массив sum_qcos_tmp.
Затем я копирую каждый локальный массив в глобальную одномерную матрицу sum_qcos_part.< br> Мне нужно добавить эти столбцы матрицы для моей цели, это то, что делает каждый рабочий элемент перед использованием результата. Вот код

__kernel __attribute__((vec_type_hint(double4))) void energy_forces( const int atom_number, 
                                         const int nvect,
                                 __global double4 *kvect,__global double *qcos,__global double *qsin,
                                 __global double *cst_ewald ,
                                 __global double4 *positions,
                                 __global double4 *forces_r,               
                                 __global double *sum_qcos_part,__global double *sum_qsin_part)                              
{


  int i = 0 ;
  int gti = 0 , ggi = 0 , lti = 0;

  double kr = (double)0.0 ;
  double ss = (double)0.0 , cc = (double)0.0 ;
  double prod = (double)0.0 ;

  double valqcos = 0. , valqsin = 0. ;  

  double4 zeroes_4 = (double4){ 0.0,0.0,0.0,0.0 };

  double sum_qcos_i[NVECTOR_MAX] ;
  double sum_qsin_i[NVECTOR_MAX] ;    

  #if defined NVECTOR_MAX
  __local double sum_qcos_tmp[NVECTOR_MAX] ;
  __local double sum_qsin_tmp[NVECTOR_MAX] ;         
  #endif

  lti = get_local_id(0);
  ggi = get_group_id(0); 

  for (k=0;k<nvect;k++) {         /*k-vectors*/
 sum_qcos_tmp[k] = .0 ;
 sum_qsin_tmp[k] = .0 ;  
 sum_qcos_i[k] = .0 ;
 sum_qsin_i[k] = .0 ;
            }  

  double fk = (double)0.0 ; 
  double4 fr_i = zeroes_4 ;
  double4 kvec_i = zeroes_4;        

  for (gti = get_global_id(0); gti < atom_number; gti += get_global_size(0))
   {

 pos_i = positions[gti];

 for (k=0;k<nvect;k++) {                           /* sum over k-vectors to compute QCOS and QSIN for Ewald sum*/

   prod = dot((double4)pos_i,(double4)kvect[k]);
   ss = (double)sincos(-prod,&cc);
   valqcos = cc ;
   valqsin = ss ; 
//       valqcos = 1. ;
//       valqsin = 1. ;       
   qcos[gti*NVECTOR_MAX+k] = valqcos ;
   qsin[gti*NVECTOR_MAX+k] = valqsin ;
   sum_qcos_i[k] = valqcos ;                     /*  private variable */
   sum_qsin_i[k] = valqsin ;  

                           }                          /* end sum over k-vectors to compute QCOS and QSIN for Ewald sum*/

}    // end for gti 

  int ii = 0 ;

  for ( ii = 0;ii<get_local_size(0);ii++ )
  { 
if (lti == ii)
  { 
 for (k=0;k<nvect;k++) 
    {                   /* k-vectors */               
       sum_qcos_tmp[k] += sum_qcos_i[k] ;     /* accumulates private data to local variable */
       sum_qsin_tmp[k] += sum_qsin_i[k] ; 
    } 
 barrier(CLK_LOCAL_MEM_FENCE|CLK_GLOBAL_MEM_FENCE) ;    
 }
  }

  if (lti == 0)
   {
     for (k=0;k<nvect;k++) {  
      sum_qcos_part[ggi*NVECTOR_MAX+k] = sum_qcos_tmp[k] ;  /* cp local data to global array */    
      sum_qsin_part[ggi*NVECTOR_MAX+k] = sum_qsin_tmp[k] ;
                           }    
   }

  int iii = 0 ;

  for (gti = get_global_id(0); gti < atom_number; gti += get_global_size(0))
   {

 fr_i = zeroes_4 ;

 barrier(CLK_LOCAL_MEM_FENCE|CLK_GLOBAL_MEM_FENCE) ;

 for (k=0;k<nvect;k++) 
  {   

    sum_qcos_i[k] = .0 ;
    sum_qsin_i[k] = .0 ;

   for (iii=0;iii<get_num_groups(0);iii++)
    {  
      sum_qcos_i[k] += sum_qcos_part[iii*NVECTOR_MAX+k] ;
      sum_qsin_i[k] += sum_qsin_part[iii*NVECTOR_MAX+k] ;     
    }

 } 

 barrier(CLK_LOCAL_MEM_FENCE|CLK_GLOBAL_MEM_FENCE) ;

 for (k=0;k<nvect;k++) 
  {

    fk =  ( sum_qcos_i[k]*qsin[gti*NVECTOR_MAX+k] - sum_qsin_i[k]*qcos[gti*NVECTOR_MAX+k] ) ;               
    fr_i += cst_ewald[k] * fk * kvect[k] ;    

  }

#if defined(SCALAR_KERNELS)
forces_r[gti].x = fr_i.x;
forces_r[gti].y = fr_i.y;
forces_r[gti].z = fr_i.z;     
forces_r[gti].w = .0 ;        
#elif defined(VECTOR_KERNELS)
forces_r[gti] = fr_i;   
#endif

  }    // end for gti  

}

Это ядро ​​не работает, и я не могу понять почему.
Некоторые подсказки были бы очень полезны здесь.
Спасибо.


person Eric    schedule 10.03.2015    source источник
comment
извините, да, я должен был объяснить. сумма вектора force_r, который я выполняю на ЦП, примерно вдвое больше, чем правильное значение, более или менее определенное значение, которое всегда меняется.   -  person Eric    schedule 11.03.2015


Ответы (2)


Добавление барьера помогло:

for ( ii = 0;ii<get_local_size(0);ii++ )
{ 
if (lti == ii)
  { 
    barrier(CLK_LOCAL_MEM_FENCE|CLK_GLOBAL_MEM_FENCE) ;      
    for (k=0;k<nvect;k++) 
    {                   /* k-vectors */               
      sum_qcos_tmp[k] += sum_qcos_i[k] ;      /* accumulates private data to local variable */
      sum_qsin_tmp[k] += sum_qsin_i[k] ; 
    } 

  }
}

Финал вектора force_r по-прежнему неверен, но теперь он всегда одинаков.

person Eric    schedule 11.03.2015

На самом деле проблема не решена.
Я определяю глобальный размер работы на основе количества частиц, чтобы каждый рабочий элемент заботился об одной частице.
В своих расчетах я скалярно умножаю каждую частицу на координаты с определенным числом. векторов.
Моя проблема в том, что результат этих скалярных произведений зависит от размера группы. Я помещаю векторы в массив double4. Глобальный размер работы варьируется примерно от 1000 до 10000, тогда как количество векторов, которые я использую для скалярного произведения, всегда составляет около 200. Мне интересно, есть ли требования к размеру массивов в отношении глобального размера работы.

for (gti = get_global_id(0); gti < atom_number; gti += get_global_size(0))
 {
   pos_i = positions[gti];

   for (k=0;k<nvect;k++) {                           /* sum over k-vectors to compute QCOS and QSIN for Ewald sum*/

 prod = dot((double4)pos_i,(double4)kvect[k]);
 ss = (double)sincos(-prod,&cc);
 valqcos = cc ;
 valqsin = ss ;   
 qcos[gti*NVECTOR_MAX+k] = valqcos ;
 qsin[gti*NVECTOR_MAX+k] = valqsin ;
 sum_qcos_i[k] = valqcos ;                     /*  private variable */
 sum_qsin_i[k] = valqsin ;  

                         }                          /* end sum over k-vectors to compute QCOS and QSIN for Ewald sum*/
 }    // end for gtiforgot 

Любые подсказки здесь?

person Eric    schedule 18.03.2015