CLBufferWrite

OpenCL 버퍼에 쓰고 작성된 요소 수를 반환합니다.

uint  CLBufferWrite(
   int          buffer,                    // OpenCL 버퍼에 대한 핸들
   const void&  data[],                    // 값들의 배열
   uint         buffer_offset=0,           // OpenCL 버퍼의 오프셋(바이트), 기본적으로 0
   uint         data_offset=0,             // 요소 배열의 오프셋, 기본적으로 0
   uint         data_count=WHOLE_ARRAY     // 기본적으로 전체 배열을 쓰기 위한 배열의 값 수
   );

행렬과 벡터를 처리하기 위한 버전이 있습니다.

행렬의 값을 버퍼에 쓰고 성공하면 true를 반환합니다.

uint  CLBufferWrite(
   int           buffer,                    // OpenCL 버퍼에 대한 핸들
   uint          buffer_offset,             // OpenCL 버퍼의 오프셋(바이트)
   matrix<T>     &mat                       // 버퍼에 쓰기 위한 값 행렬
   );

벡터의 값을 버퍼에 쓰고 성공하면 true를 반환합니다.

uint  CLBufferWrite(
   int           buffer,                    // OpenCL 버퍼에 대한 핸들
   uint          buffer_offset,             // OpenCL 버퍼의 오프셋(바이트)
   vector<T>     &vec                       // 버퍼에 쓰기 위한 값 벡터
   );

Parameter

buffer

[in]  OpenCL 버퍼의 핸들.

data[]

[in]  OpenCL 버퍼에 기록해야 하는 값의 배열. 참조에 의해 통과됨

buffer_offset

[in]  쓰기가 시작되는 OpenCL 버퍼의 오프셋(바이트). 기본적으로 쓰기의 시작은 버퍼의 맨 처음입니다.

data_offset

[in]  OpenCL 버퍼에 쓰여지는 배열의 값을 시작하는 첫 번째 배열 요소의 인덱스. 기본적으로 배열의 맨 처음부터 값을 가져옵니다.

data_count

[in]  기록해야 할 값 수. 기본적으로 배열의 모든 값.

mat

[out] 버퍼에서 데이터를 읽기 위한 행렬은 다음 세 가지 유형 중 하나일 수 있습니다 - matrix, matrixf 또는 matrixc.

vec

[out]  버퍼에서 데이터를 읽기 위한 벡터는 vector, vectorf 또는 vectorc의 세 가지 유형 중 하나일 수 있습니다.

반환값

작성된 요소 수. 오류 발생 시 0이 반환됩니다. 오류에 대한 자세한 내용은 GetLastError() 함수를 사용하십시오.

true 행렬 또는 벡터가 성공적으로 처리될 경우 그렇지 않을 경우 false.

참고

1차원 배열의 경우, OpenCL 버퍼에 쓰기 위한 데이터 읽기가 시작되는 요소의 수는 AS_SERIES 플래그를 고려하여 계산됩니다.

2개 이상의 차원으로 구성된 배열은 1차원으로 표시됩니다. 이 경우 data_offset은 프레젠테이션에서 건너뛸 요소의 수이지 첫 번째 차원의 요소 수가 아닙니다.

 

MatMul 메서드를 사용한 행렬 곱셈 및 OpenCL의 병렬 컴퓨팅의

#define M       3000      // 첫 번째 행렬의 행 수
#define K       2000      // 첫 번째 행렬의 열 수는 두 번째 행렬의 행 수와 같습니다. 
#define N       3000      // 두 번째 행렬의 열 수
 
/+------------------------------------------------------------------+
const string clSrc=
  "#define N     "+IntegerToString(N)+"                              \r\n"
  "#define K     "+IntegerToString(K)+"                              \r\n"
  "                                                                  \r\n"
  "__kernel void matricesMul( __global float *in1,                   \r\n"
  "                           __global float *in2,                   \r\n"
  "                           __global float *out  )                 \r\n"
  "{                                                                 \r\n"
  "  int m = get_global_id( 0 );                                     \r\n"
  "  int n = get_global_id( 1 );                                     \r\n"
  "  float sum = 0.0;                                                \r\n"
  "  for( int k = 0; k < K; k ++ )                                   \r\n"
  "     sum += in1[ m * K + k ] * in2[ k * N + n ];                  \r\n"
  "  out[ m * N + n ] = sum;                                         \r\n"
  "}                                                                 \r\n";
/+------------------------------------------------------------------+
//| 프로그램 시작 함수 스크립트                                 |
/+------------------------------------------------------------------+
void OnStart()
 {
//--- 랜덤 넘버 생성기 초기화
  MathSrand((int)TimeCurrent());
//--- 랜덤 값으로 주어진 크기의 행렬 채우기
  matrixf mat1(MKMatrixRandom) ;    // first matrix
  matrixf mat2(KNMatrixRandom);     // second matrix
 
//--- 네이티브 메서드를 사용하여 행렬의 곱을 계산
  uint start=GetTickCount();
  matrixf matrix_naive=matrixf::Zeros(MN);// 두 행렬을 곱한 결과가 여기에 설정됩니다.
  for(int m=0m<Mm++)
    for(int k=0k<Kk++)
      for(int n=0n<Nn++)
        matrix_naive[m][n]+=mat1[m][k]*mat2[k][n];
  uint time_naive=GetTickCount()-start;   
     
//--- MatMull을 통해 행렬의 곱을 계산
  start=GetTickCount();
  matrixf matrix_matmul=mat1.MatMul(mat2);
  uint time_matmul=GetTickCount()-start;     
  
//--- OpenCL에서 행렬의 곱 계산
  matrixf matrix_opencl=matrixf::Zeros(MN);
  int cl_ctx;             // 컨텍스트 핸들
  if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
   {
    Print("OpenCL not found, leaving");
    return;
   }
  int cl_prg;             // 프로그램 핸들 
  int cl_krn;             // 커널 핸들
  int cl_mem_in1;         // 첫번째(입력) 버퍼 핸들
  int cl_mem_in2;         // 두번째(입력) 버퍼 핸들e
  int cl_mem_out;         // 세번째(입력) 버퍼 핸들
//--- 프로그램과 커널 생성
  cl_prg = CLProgramCreate(cl_ctxclSrc);
  cl_krn = CLKernelCreate(cl_prg"matricesMul");
//--- 3개의 행렬에 대해 3개의 버퍼를 모두 생성
  cl_mem_in1=CLBufferCreate(cl_ctxM*K*sizeof(float), CL_MEM_READ_WRITE);
  cl_mem_in2=CLBufferCreate(cl_ctxK*N*sizeof(float), CL_MEM_READ_WRITE);
//--- 세번째 행렬 - 출력
  cl_mem_out=CLBufferCreate(cl_ctxM*N*sizeof(float), CL_MEM_READ_WRITE);
//--- 커널 인수 설정
  CLSetKernelArgMem(cl_krn0cl_mem_in1);
  CLSetKernelArgMem(cl_krn1cl_mem_in2);
  CLSetKernelArgMem(cl_krn2cl_mem_out);
//--- 장치 버퍼에 행렬 쓰기
  CLBufferWrite(cl_mem_in10mat1);
  CLBufferWrite(cl_mem_in20mat2);
  CLBufferWrite(cl_mem_out0matrix_opencl);
//--- OpenCL 코드 실행 시간 시작
  start=GetTickCount();
//--- 태스크 작업 영역의 매개변수를 설정하고 OpenCL 프로그램을 실행
  uint  offs[2] = {00};
  uint works[2] = {MN};
  start=GetTickCount();  
  bool ex=CLExecute(cl_krn2offsworks);
//--- 결과를 행렬로 계산
  if(CLBufferRead(cl_mem_out0matrix_opencl))
    PrintFormat("[%d x %d] matrix read: "matrix_opencl.Rows(), matrix_opencl.Cols());
   else
      Print("CLBufferRead(cl_mem_out, 0, matrix_opencl failed. Error ",GetLastError()); 
  uint time_opencl=GetTickCount()-start;   
  Print("Compare calculation time using each method");
  PrintFormat("Naive product time = %d ms",time_naive);
  PrintFormat("MatMul product time = %d ms",time_matmul);
  PrintFormat("OpenCl product time = %d ms",time_opencl);  
//--- 모든 OpenCL 컨텍스트 해제
  CLFreeAll(cl_ctxcl_prgcl_krncl_mem_in1cl_mem_in2cl_mem_out);
 
//--- 얻은 모든 결과 행렬을 서로 비교
  Print("How many discrepancy errors are there between result matrices?");
  ulong errors=matrix_naive.Compare(matrix_matmul,(float)1e-12);
  Print("matrix_direct.Compare(matrix_matmul,1e-12)=",errors);
  errors=matrix_matmul.Compare(matrix_opencl,float(1e-12));
  Print("matrix_matmul.Compare(matrix_opencl,1e-12)=",errors);
/*
  결과:
   
   [3000 x 3000] matrix read: 
  각 메서드별 계산 시간 비교
   Naive product time = 54750 ms
   MatMul product time = 4578 ms
   OpenCl product time = 922 ms
  결과 행렬 사이에 얼마나 많은 불일치 오류가 있을까요?
   matrix_direct.Compare(matrix_matmul,1e-12)=0
   matrix_matmul.Compare(matrix_opencl,1e-12)=0
*/  
 }
/+------------------------------------------------------------------+
//| 행렬을 임의의 값으로 채웁니다.                              |
/+------------------------------------------------------------------+
void MatrixRandom(matrixfm)
 {
  for(ulong r=0r<m.Rows(); r++)
   {
    for(ulong c=0c<m.Cols(); c++)
     {
      m[r][c]=(float)((MathRand()-16383.5)/32767.);
     }
   }
 }
/+------------------------------------------------------------------+
//| 모든 OpenCL 컨텍스트 해제                                      |
/+------------------------------------------------------------------+
void CLFreeAll(int cl_ctxint cl_prgint cl_krn,
               int cl_mem_in1int cl_mem_in2int cl_mem_out)
 {
//--- OpenCL에서 생성한 모든 컨텍스트를 역순으로 삭제
  CLBufferFree(cl_mem_in1);
  CLBufferFree(cl_mem_in2);
  CLBufferFree(cl_mem_out);
  CLKernelFree(cl_krn);
  CLProgramFree(cl_prg);
  CLContextFree(cl_ctx);
 }