2019-05-18 10:24:07 +03:00
|
|
|
|
uses OpenCL;
|
|
|
|
|
|
uses System;
|
|
|
|
|
|
uses System.Runtime.InteropServices;
|
|
|
|
|
|
|
|
|
|
|
|
const
|
2019-05-24 13:54:13 +03:00
|
|
|
|
MatrW = 4; // можно поменять на любое положительное значение
|
|
|
|
|
|
|
2019-06-06 18:18:55 +03:00
|
|
|
|
VecByteSize = MatrW*8;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
MatrL = MatrW*MatrW;
|
|
|
|
|
|
MatrByteSize = MatrL*8;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
|
2019-05-18 10:24:07 +03:00
|
|
|
|
begin
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Randomize(0); // чтоб при каждом выполнении были одинаковые результаты
|
2019-05-18 10:24:07 +03:00
|
|
|
|
var ec: ErrorCode;
|
|
|
|
|
|
|
|
|
|
|
|
// Инициализация
|
|
|
|
|
|
|
|
|
|
|
|
var platform: cl_platform_id;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
cl.GetPlatformIDs(1, platform, IntPtr.Zero).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
|
|
|
|
|
var device: cl_device_id;
|
2020-08-04 02:26:50 +03:00
|
|
|
|
cl.GetDeviceIDs(platform, DeviceType.DEVICE_TYPE_ALL, 1,device,IntPtr.Zero).RaiseIfError;
|
2019-07-18 03:47:28 +03:00
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
var context := cl.CreateContext(nil, 1,device, nil,IntPtr.Zero, ec);
|
2019-05-18 10:24:07 +03:00
|
|
|
|
ec.RaiseIfError;
|
|
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
var command_queue := cl.CreateCommandQueueWithProperties(context, device, nil, ec);
|
2019-05-18 10:24:07 +03:00
|
|
|
|
ec.RaiseIfError;
|
|
|
|
|
|
|
|
|
|
|
|
// Чтение и компиляция .cl файла
|
|
|
|
|
|
|
|
|
|
|
|
{$resource MatrMlt.cl}
|
2020-08-04 02:26:50 +03:00
|
|
|
|
var prog_str := System.IO.StreamReader.Create(
|
|
|
|
|
|
System.Reflection.Assembly.GetCallingAssembly.GetManifestResourceStream('MatrMlt.cl')
|
|
|
|
|
|
).ReadToEnd;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
var prog := cl.CreateProgramWithSource(
|
|
|
|
|
|
context,
|
|
|
|
|
|
1,
|
|
|
|
|
|
new string[](prog_str),
|
2020-03-13 05:28:53 +03:00
|
|
|
|
nil,
|
2019-05-18 10:24:07 +03:00
|
|
|
|
ec
|
|
|
|
|
|
);
|
|
|
|
|
|
ec.RaiseIfError;
|
|
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
cl.BuildProgram(prog, 1,device, nil, nil,IntPtr.Zero).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
|
|
|
|
|
var MatrMltMatrKernel := cl.CreateKernel(prog, 'MatrMltMatr', ec);
|
|
|
|
|
|
ec.RaiseIfError;
|
|
|
|
|
|
|
|
|
|
|
|
var MatrMltVecKernel := cl.CreateKernel(prog, 'MatrMltVec', ec);
|
|
|
|
|
|
ec.RaiseIfError;
|
|
|
|
|
|
|
|
|
|
|
|
// Подготовка параметров
|
|
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Writeln('Матрица A:');
|
2019-05-18 10:24:07 +03:00
|
|
|
|
var A := MatrRandomReal(MatrW,MatrW,0,1).Println;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Writeln;
|
|
|
|
|
|
var A_buf := cl.CreateBuffer(context, MemFlags.MEM_READ_WRITE, new UIntPtr(MatrByteSize),IntPtr.Zero, ec);
|
2019-05-18 10:24:07 +03:00
|
|
|
|
ec.RaiseIfError;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
cl.EnqueueWriteBuffer(command_queue, A_buf, Bool.BLOCKING, new UIntPtr(0),new UIntPtr(MatrByteSize), A[0,0], 0,nil,IntPtr.Zero).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Writeln('Матрица B:');
|
2019-05-18 10:24:07 +03:00
|
|
|
|
var B := MatrRandomReal(MatrW,MatrW,0,1).Println;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Writeln;
|
|
|
|
|
|
var B_buf := cl.CreateBuffer(context, MemFlags.MEM_READ_WRITE, new UIntPtr(MatrByteSize),IntPtr.Zero, ec);
|
2019-05-18 10:24:07 +03:00
|
|
|
|
ec.RaiseIfError;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
cl.EnqueueWriteBuffer(command_queue, B_buf, Bool.BLOCKING, new UIntPtr(0),new UIntPtr(MatrByteSize), B[0,0], 0,nil,IntPtr.Zero).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Writeln('Вектор V1:');
|
2019-06-06 18:18:55 +03:00
|
|
|
|
var V1 := ArrRandomReal(MatrW);
|
|
|
|
|
|
V1.Println;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Writeln;
|
|
|
|
|
|
var V1_buf := cl.CreateBuffer(context, MemFlags.MEM_READ_WRITE, new UIntPtr(VecByteSize),IntPtr.Zero, ec);
|
2019-05-18 10:24:07 +03:00
|
|
|
|
ec.RaiseIfError;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
cl.EnqueueWriteBuffer(command_queue, V1_buf, Bool.BLOCKING, new UIntPtr(0),new UIntPtr(VecByteSize), V1[0], 0,nil,IntPtr.Zero).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
var C_buf := cl.CreateBuffer(context, MemFlags.MEM_READ_WRITE, new UIntPtr(MatrByteSize),IntPtr.Zero, ec);
|
2019-05-18 10:24:07 +03:00
|
|
|
|
ec.RaiseIfError;
|
|
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
var V2_buf := cl.CreateBuffer(context, MemFlags.MEM_READ_WRITE, new UIntPtr(VecByteSize),IntPtr.Zero, ec);
|
2019-05-18 10:24:07 +03:00
|
|
|
|
ec.RaiseIfError;
|
|
|
|
|
|
|
|
|
|
|
|
var MatrWParam := MatrW;
|
|
|
|
|
|
|
|
|
|
|
|
// Выполнение C := A*B
|
|
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
cl.SetKernelArg(MatrMltMatrKernel, 0, new UIntPtr(UIntPtr.Size), A_buf).RaiseIfError;
|
|
|
|
|
|
cl.SetKernelArg(MatrMltMatrKernel, 1, new UIntPtr(UIntPtr.Size), B_buf).RaiseIfError;
|
|
|
|
|
|
cl.SetKernelArg(MatrMltMatrKernel, 2, new UIntPtr(UIntPtr.Size), C_buf).RaiseIfError;
|
2020-08-04 02:26:50 +03:00
|
|
|
|
cl.SetKernelArg(MatrMltMatrKernel, 3, new UIntPtr(sizeof(integer)), @MatrWParam).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
var k1_ev: cl_event;
|
|
|
|
|
|
cl.EnqueueNDRangeKernel(command_queue, MatrMltMatrKernel, 2, nil,new UIntPtr[](new UIntPtr(MatrW),new UIntPtr(MatrW)),nil, 0,nil,k1_ev).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
|
|
|
|
|
// Выполнение V2 := C*V
|
|
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
cl.SetKernelArg(MatrMltVecKernel, 0, new UIntPtr(UIntPtr.Size), C_buf).RaiseIfError;
|
|
|
|
|
|
cl.SetKernelArg(MatrMltVecKernel, 1, new UIntPtr(UIntPtr.Size), V1_buf).RaiseIfError;
|
|
|
|
|
|
cl.SetKernelArg(MatrMltVecKernel, 2, new UIntPtr(UIntPtr.Size), V2_buf).RaiseIfError;
|
2020-08-04 02:26:50 +03:00
|
|
|
|
cl.SetKernelArg(MatrMltVecKernel, 3, new UIntPtr(sizeof(integer)), @MatrWParam).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
var k2_ev: cl_event;
|
|
|
|
|
|
cl.EnqueueNDRangeKernel(command_queue, MatrMltVecKernel, 1, nil,new UIntPtr[](new UIntPtr(MatrW)),nil, 1,k1_ev,k2_ev).RaiseIfError;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
|
|
|
|
|
// Чтение и вывод результата
|
|
|
|
|
|
|
2020-02-26 07:34:25 +03:00
|
|
|
|
// Внимание! В отличии от OpenCLABC - тут чтение "C_buf" не обязательно начнётся сразу после выполнения "k1_ev"
|
|
|
|
|
|
// Большинство реализаций OpenCL не поддерживают асинхронные очереди
|
|
|
|
|
|
// Чтоб получить асинхронное выполнение "cl.Enqueue*" команд - надо несколько вызовов "cl.CreateCommandQueueWithProperties"
|
|
|
|
|
|
cl.EnqueueReadBuffer(command_queue, C_buf, Bool.BLOCKING, new UIntPtr(0), new UIntPtr(MatrByteSize), A[0,0], 1,k1_ev,IntPtr.Zero).RaiseIfError;
|
|
|
|
|
|
Writeln('Матрица С = A*B:');
|
2019-05-18 10:24:07 +03:00
|
|
|
|
A.Println;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Writeln;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
2020-08-04 02:26:50 +03:00
|
|
|
|
cl.EnqueueReadBuffer(command_queue, V2_buf, Bool.BLOCKING, new UIntPtr(0), new UIntPtr(VecByteSize), V1[0], 1,k2_ev,IntPtr.Zero).RaiseIfError;
|
2020-02-26 07:34:25 +03:00
|
|
|
|
Writeln('Вектор V2 = C*V1:');
|
2019-06-06 18:18:55 +03:00
|
|
|
|
V1.Println;
|
2019-05-18 10:24:07 +03:00
|
|
|
|
|
|
|
|
|
|
end.
|