#define M 3000 // birinci matristeki satır sayısı
#define K 2000 // birinci matristeki sütun sayısı ikinci matristeki satır sayısına eşittir
#define N 3000 // ikinci matristeki sütun sayısı
//+------------------------------------------------------------------+
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";
//+------------------------------------------------------------------+
//| Komut dosyası başlatma fonksiyonu |
//+------------------------------------------------------------------+
void OnStart()
{
//--- rastgele sayı üreticisini başlat
MathSrand((int)TimeCurrent());
//--- matrisleri rastgele değerlerle doldur
matrixf mat1(M, K, MatrixRandom) ; // birinci matris
matrixf mat2(K, N, MatrixRandom); // ikinci matris
//--- saf yöntem kullanarak matrislerin çarpımını hesapla
uint start=GetTickCount();
matrixf matrix_naive=matrixf::Zeros(M, N);// iki matrisin çarpılmasının sonucu burada belirlenir
for(int m=0; m<M; m++)
for(int k=0; k<K; k++)
for(int n=0; n<N; n++)
matrix_naive[m][n]+=mat1[m][k]*mat2[k][n];
uint time_naive=GetTickCount()-start;
//--- MatMul aracılığıyla matrislerin çarpımını hesapla
start=GetTickCount();
matrixf matrix_matmul=mat1.MatMul(mat2);
uint time_matmul=GetTickCount()-start;
//--- OpenCL'de matrislerin çarpımını hesapla
matrixf matrix_opencl=matrixf::Zeros(M, N);
int cl_ctx; // içerik tanıtıcısı
if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
{
Print("OpenCL bulunamadı, çıkış yapılıyor");
return;
}
int cl_prg; // program tanıtıcısı
int cl_krn; // çekirdek tanıtıcısı
int cl_mem_in1; // birinci (girdi) arabellek tanıtıcısı
int cl_mem_in2; // ikinci (girdi) arabellek tanıtıcısı
int cl_mem_out; // üçüncü (çıktı) arabellek tanıtıcısı
//--- programı ve çekirdeği oluştur
cl_prg = CLProgramCreate(cl_ctx, clSrc);
cl_krn = CLKernelCreate(cl_prg, "matricesMul");
//--- üç matris için üç arabelleğin tümünü oluştur
cl_mem_in1=CLBufferCreate(cl_ctx, M*K*sizeof(float), CL_MEM_READ_WRITE);
cl_mem_in2=CLBufferCreate(cl_ctx, K*N*sizeof(float), CL_MEM_READ_WRITE);
//--- üçüncü matris - çıktı
cl_mem_out=CLBufferCreate(cl_ctx, M*N*sizeof(float), CL_MEM_READ_WRITE);
//--- çekirdek argümanlarını ayarla
CLSetKernelArgMem(cl_krn, 0, cl_mem_in1);
CLSetKernelArgMem(cl_krn, 1, cl_mem_in2);
CLSetKernelArgMem(cl_krn, 2, cl_mem_out);
//--- matrisleri cihaz arabelleklerine yaz
CLBufferWrite(cl_mem_in1, 0, mat1);
CLBufferWrite(cl_mem_in2, 0, mat2);
CLBufferWrite(cl_mem_out, 0, matrix_opencl);
//--- OpenCL kodunu çalıştırma zamanı başlangıcı
start=GetTickCount();
//--- görev çalışma alanının parametrelerini ayarla ve OpenCL programını çalıştır
uint offs[2] = {0, 0};
uint works[2] = {M, N};
start=GetTickCount();
bool ex=CLExecute(cl_krn, 2, offs, works);
//--- sonucu hesapla
if(CLBufferRead(cl_mem_out, 0, matrix_opencl))
PrintFormat("[%d x %d] matris okuması: ", matrix_opencl.Rows(), matrix_opencl.Cols());
else
Print("CLBufferRead(cl_mem_out, 0, matrix_opencl başarısız oldu. Hata ",GetLastError());
uint time_opencl=GetTickCount()-start;
Print("Her yöntemi kullanarak hesaplama sürelerini karşılaştır");
PrintFormat("Saf yöntemle çarpma süresi = %d ms",time_naive);
PrintFormat("MatMul metoduyla çarpma süresi = %d ms",time_matmul);
PrintFormat("OpenCl ile çarpma süresi = %d ms",time_opencl);
//--- tüm OpenCL içeriklerini bırak
CLFreeAll(cl_ctx, cl_prg, cl_krn, cl_mem_in1, cl_mem_in2, cl_mem_out);
//--- tüm sonuç matrisleri birbirleriyle karşılaştır
Print("Sonuç matrisler arasında kaç tane tutarsızlık hatası var?");
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);
/*
Sonuç:
[3000 x 3000] matris okuması:
Her yöntemi kullanarak hesaplama sürelerini karşılaştır
Saf yöntemle çarpma süresi = 54750 ms
MatMul metoduyla çarpma süresi = 4578 ms
OpenCl ile çarpma süresi = 922 ms
Sonuç matrisler arasında kaç tane tutarsızlık hatası var?
matrix_direct.Compare(matrix_matmul,1e-12)=0
matrix_matmul.Compare(matrix_opencl,1e-12)=0
*/
}
//+------------------------------------------------------------------+
//| Matrisi rastgele değerlerle doldur |
//+------------------------------------------------------------------+
void MatrixRandom(matrixf& m)
{
for(ulong r=0; r<m.Rows(); r++)
{
for(ulong c=0; c<m.Cols(); c++)
{
m[r][c]=(float)((MathRand()-16383.5)/32767.);
}
}
}
//+------------------------------------------------------------------+
//| Tüm OpenCL içeriklerini bırak |
//+------------------------------------------------------------------+
void CLFreeAll(int cl_ctx, int cl_prg, int cl_krn,
int cl_mem_in1, int cl_mem_in2, int cl_mem_out)
{
//--- OpenCL tarafından ters sırada oluşturulan tüm içerikleri sil
CLBufferFree(cl_mem_in1);
CLBufferFree(cl_mem_in2);
CLBufferFree(cl_mem_out);
CLKernelFree(cl_krn);
CLProgramFree(cl_prg);
CLContextFree(cl_ctx);
}
|