CLBufferRead

Lit le tampon OpenCL au tableau et rend la quantité d'éléments lus.

uint  CLBufferRead(
   int          buffer,                    // le handle sur le tampon OpenCL
   const void&  data[],                    // le tableau des valeurs
   uint         buffer_offset=0,           // le décalage dans le tampon OpenCL en octets, par défaut 0
   uint         data_offset=0,             // le décalage dans le tampon dans les éléments, par défaut 0
   uint         data_count=WHOLE_ARRAY     // le nombre des valeurs du tableau pour la lecture, par défaut tout le tableau
   );

Il existe d'autres versions pour l'utilisation de matrices et vecteurs.

Lit le buffer OpenCL et l'écrit dans la matrice et retourne true en cas de succès.

uint  CLBufferRead(
   int           buffer,                    // handle vers le buffer OpenCL
   uint          buffer_offset,             // décalage dans le buffer OpenCL en octets
   const matrxi& mat,                       // la matrice dans laquelle les valeurs du buffer seront écrites
   ulong         rows=-1,                   // le nombre de lignes de la matrice
   ulong         cols=-1                    // le nombre de colonnes de la matrice
   );

Lit le buffer OpenCL et l'écrit dans le vecteur et retourne true en cas de succès.

uint  CLBufferRead(
   int           buffer,                    // handle vers le buffer OpenCL
   uint          buffer_offset,             // décalage dans le buffer OpenCL en octets
   const vector& vec,                       // le vecteur dans lequel les valeurs du buffer seront écrites
   ulong         size-1,                    // longueur du vecteur
   );

Paramètres

buffer

[in]  Le handle du tampon OpenCL.

data[]

[in]  Le massif pour la réception des valeurs du tampon OpenCL. est transmis selon la référence.

buffer_offset

[in]  Le décalage dans le tampon OpenCL en octets, par lequel commence la lecture. Par défaut la lecture commence par le début du tampon.

data_offset

[in]  L'index du premier élément du massif pour l'inscription des valeurs du tampon OpenCL. Par défaut la lecture l'inscription des valeurs lues au tableau commence par index nul.

data_count

[in]  Le nombre de valeurs, lesquelles il faut lire. Tout le tampon OpenCL est lu par défaut.

mat

[out]  La matrice pour les lire les données du buffer peut être de 3 types : matrix, matrixf ou matrixc.

vec

[out]  Le vecteur pour les lire les données du buffer peut être de 3 types : vector, vectorf ou vectorc.

rows=-1

[in]  Si le paramètre est spécifié, le paramètre cols doit également être spécifié. Si les dimensions de la nouvelle matrice ne sont pas spécifiées, les dimensions courantes seront utilisées. Si la valeur est -1, alors le nombre de lignes ne changera pas.

cols=-1

[in]  Si le paramètre n'est pas spécifié, le paramètre rows doit être spécifié également. La matrice adhère à la règle suivante : soit les 2 paramètres sont spécifiés, soit aucun, ou sinon une erreur est générée. Si les 2 paramètres (rows et cols) sont spécifiés, la taille de la matrice sera changée. Si -1, le nombre de colonnes ne sera pas changé.

size=-1

[in]  Si le paramètre n'est pas spécifié ou si sa valeur est -1, la longueur du vecteur ne changera pas.

La valeur rendue

Le nombre d'éléments lus, en cas de l'erreur 0 se revient. Pour recevoir l'information sur l'erreur, utilisez la fonction GetLastError().

true si une matrice ou un vecteur est géré avec succès, sinon false.

Note

Pour les tableaux unidimentionnels le numéro de l'élément, auquel commence l'inscription des données du tampon OpenCL, est calculé en prenant en compte le drapeau AS_SERIES.

Le tableau avec la dimension deux et plus est présenté comme unidimentionnel. Dans ce cas data_offset — c'est une quantité d'éléments, qu'il faut manquer dans la représentation, et non le nombre d'éléments dans une première dimension.

Exemple de calcul de Pi en utilisant l'équation :

pi_calculation_formula

#define  _num_steps        1000000000
#define  _divisor          40000
#define  _step             1.0 / _num_steps
#define  _intrnCnt         _num_steps / _divisor
 
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string D2S(double argint digits) { return DoubleToString(argdigits); }
string I2S(int arg)                { return IntegerToString(arg); }
 
//--- code du programme OpenCL
const string clSource=
  "#define _step "+D2S(_step12)+"                   \r\n"
  "#define _intrnCnt "+I2S(_intrnCnt)+"               \r\n"
  "                                                   \r\n"
  "__kernel void Pi( __global double *out )           \r\n"
  "{                                                  \r\n"
  "  int i = get_global_id( 0 );                      \r\n"
  "  double partsum = 0.0;                            \r\n"
  "  double x = 0.0;                                  \r\n"
  "  long from = i * _intrnCnt;                       \r\n"
  "  long to = from + _intrnCnt;                      \r\n"
  "  for( long j = from; j < to; j ++ )               \r\n"
  "  {                                                \r\n"
  "     x = ( j + 0.5 ) * _step;                      \r\n"
  "     partsum += 4.0 / ( 1. + x * x );              \r\n"
  "  }                                                \r\n"
  "  out[ i ] = partsum;                              \r\n"
  "}                                                  \r\n";
 
//+------------------------------------------------------------------+
//| Fonction de démarrage du programme                               |
//+------------------------------------------------------------------+
int OnStart()
 {
  Print("Calcul de Pi : pas = "+D2S(_step12)+"; _intrnCnt = "+I2S(_intrnCnt));
//--- prépare les contextes OpenCL
  int clCtx;
  if((clCtx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
   {
    Print("OpenCL non trouvé");
    return(-1);
   }
  int clPrg = CLProgramCreate(clCtxclSource);
  int clKrn = CLKernelCreate(clPrg"Pi");
  int clMem=CLBufferCreate(clCtx_divisor*sizeof(double), CL_MEM_READ_WRITE);
  CLSetKernelArgMem(clKrn0clMem);
 
  const uint offs[1]  = {0};
  const uint works[1] = {_divisor};
//--- lance le programme OpenCL
  ulong start=GetMicrosecondCount();
  if(!CLExecute(clKrn1offsworks))
   {
    Print("CLExecute(clKrn, 1, offs, works) a échoué ! Erreur "GetLastError());
    CLFreeAll(clMemclKrnclPrgclCtx);
    return(-1);
   }
//--- récupère les résultats du périphérique OpenCL
  vector buffer(_divisor);
  if(!CLBufferRead(clMem0buffer))
   {
    Print("CLBufferRead(clMem, 0, buffer) a échoué ! Erreur "GetLastError());
    CLFreeAll(clMemclKrnclPrgclCtx);
    return(-1);
   }
//--- additionne toutes les valeurs pour calculer Pi
  double Pi=buffer.Sum()*_step;
 
  double time=(GetMicrosecondCount()-start)/1000.;
  Print("OpenCL: Pi calculaté pour "+D2S(, 2)+" ms");
  Print("Pi = "+DoubleToString(Pi12));
//--- libère la mémoire
  CLFreeAll(clMemclKrnclPrgclCtx);
//--- succès
  return(0);
 }
  /*
  Calcul de Pi : pas = 0.000000001000_intrnCnt = 25000
  OpenCLPériphérique GPU  'Ellesmereselected
  OpenCLPi calculé for 99.98 ms
  Pi = 3.141592653590
  */ 
//+------------------------------------------------------------------+
//| Routine auxiliaire pour libérer la mémoire                       |
//+------------------------------------------------------------------+
void CLFreeAll(const int clMemconst int clKrnconst int clPrgconst int clCtx)
 {
  CLBufferFree(clMem);
  CLKernelFree(clKrn);
  CLProgramFree(clPrg);
  CLContextFree(clCtx);
 }