172 lines
14 KiB
MQL5
172 lines
14 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| opencl.mqh |
|
|
//| Copyright 2021, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2021, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
//+------------------------------------------------------------------+
|
|
//| Подключаем библиотеки |
|
|
//+------------------------------------------------------------------+
|
|
#include <OpenCL\OpenCL.mqh>
|
|
//+------------------------------------------------------------------+
|
|
//| Class CMyOpenCL |
|
|
//| Назначение: Класс организации работы с контекстом OpenCL |
|
|
//+------------------------------------------------------------------+
|
|
class CMyOpenCL : public COpenCL
|
|
{
|
|
public:
|
|
CMyOpenCL(void) {};
|
|
~CMyOpenCL(void) {};
|
|
template<typename T>
|
|
int AddBufferFromArray(T &data[], const uint data_array_offset, const uint data_array_count, const uint flags);
|
|
int AddBufferFromArray(matrix &data, const uint data_array_offset, const uint flags);
|
|
bool CheckBuffer(const int index);
|
|
//---
|
|
bool BufferFromMatrix(const int buffer_index, MATRIX &data, const uint data_array_offset, const uint flags);
|
|
bool BufferRead(const int buffer_index, MATRIX &data, const uint cl_buffer_offset);
|
|
bool BufferWrite(const int buffer_index, MATRIX &data, const uint cl_buffer_offset);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Метод создания буфера в контексте OpenCL |
|
|
//+------------------------------------------------------------------+
|
|
template<typename T>
|
|
int CMyOpenCL::AddBufferFromArray(T &data[], const uint data_array_offset, const uint data_array_count, const uint flags)
|
|
{
|
|
//--- Поисе свободного элемента в динамическом массиве указателей
|
|
int result = -1;
|
|
for(int i = 0; i < m_buffers_total; i++)
|
|
{
|
|
if(m_buffers[i] != INVALID_HANDLE)
|
|
continue;
|
|
result = i;
|
|
break;
|
|
}
|
|
//--- Если всободный элементне найден добавляем новый элемен в массив
|
|
if(result < 0)
|
|
{
|
|
if(ArrayResize(m_buffers, m_buffers_total + 1) > 0)
|
|
{
|
|
m_buffers_total = ArraySize(m_buffers);
|
|
result = m_buffers_total - 1;
|
|
m_buffers[result] = INVALID_HANDLE;
|
|
}
|
|
else
|
|
return result;
|
|
}
|
|
//--- Создаём буфер в контексте OpenCL
|
|
if(!BufferFromArray(result, data, data_array_offset, data_array_count, flags))
|
|
return -1;
|
|
//---
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод создания буфера в контексте OpenCL |
|
|
//+------------------------------------------------------------------+
|
|
int CMyOpenCL::AddBufferFromArray(matrix &data, const uint data_array_offset, const uint flags)
|
|
{
|
|
//--- Поисе свободного элемента в динамическом массиве указателей
|
|
int result = -1;
|
|
for(int i = 0; i < m_buffers_total; i++)
|
|
{
|
|
if(m_buffers[i] != INVALID_HANDLE)
|
|
continue;
|
|
result = i;
|
|
break;
|
|
}
|
|
//--- Если всободный элементне найден добавляем новый элемен в массив
|
|
if(result < 0)
|
|
{
|
|
if(ArrayResize(m_buffers, m_buffers_total + 1) > 0)
|
|
{
|
|
m_buffers_total = ArraySize(m_buffers);
|
|
result = m_buffers_total - 1;
|
|
m_buffers[result] = INVALID_HANDLE;
|
|
}
|
|
else
|
|
return result;
|
|
}
|
|
//--- Создаём буфер в контексте OpenCL
|
|
if(!BufferFromMatrix(result, data, data_array_offset, flags))
|
|
return -1;
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод проверки действительности указателя на буфер по индексу |
|
|
//| в динамическом массиве |
|
|
//+------------------------------------------------------------------+
|
|
bool CMyOpenCL::CheckBuffer(const int index)
|
|
{
|
|
if(index < 0 || index > m_buffers_total)
|
|
return false;
|
|
return m_buffers[index] != INVALID_HANDLE;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| BufferFromMatrix |
|
|
//+------------------------------------------------------------------+
|
|
bool CMyOpenCL::BufferFromMatrix(const int buffer_index, MATRIX &data, const uint data_array_offset, const uint flags)
|
|
{
|
|
//--- check parameters
|
|
if(m_context == INVALID_HANDLE || m_program == INVALID_HANDLE)
|
|
return(false);
|
|
if(buffer_index < 0 || buffer_index >= m_buffers_total)
|
|
return(false);
|
|
//--- buffer does not exists, create it
|
|
if(m_buffers[buffer_index] == INVALID_HANDLE)
|
|
{
|
|
uint size_in_bytes = (typename(MATRIX)=="matrix" ? sizeof(double) : sizeof(float))*(int)(data.Rows()*data.Cols());
|
|
int buffer_handle = CLBufferCreate(m_context, size_in_bytes, flags);
|
|
if(buffer_handle != INVALID_HANDLE)
|
|
{
|
|
m_buffers[buffer_index] = buffer_handle;
|
|
}
|
|
else
|
|
return(false);
|
|
}
|
|
//--- write data to OpenCL buffer
|
|
ResetLastError();
|
|
if(!CLBufferWrite(m_buffers[buffer_index], data_array_offset, data))
|
|
{
|
|
PrintFormat("Write to buffer error %d", GetLastError());
|
|
return(false);
|
|
}
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| BufferRead |
|
|
//+------------------------------------------------------------------+
|
|
bool CMyOpenCL::BufferRead(const int buffer_index, MATRIX &data, const uint cl_buffer_offset)
|
|
{
|
|
//--- check parameters
|
|
if(buffer_index < 0 || buffer_index >= m_buffers_total || data.Rows() <= 0)
|
|
return(false);
|
|
if(m_buffers[buffer_index] == INVALID_HANDLE)
|
|
return(false);
|
|
if(m_context == INVALID_HANDLE || m_program == INVALID_HANDLE)
|
|
return(false);
|
|
//--- read data from OpenCL buffer
|
|
if(!CLBufferRead(m_buffers[buffer_index], cl_buffer_offset, data))
|
|
return(false);
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| BufferWrite |
|
|
//+------------------------------------------------------------------+
|
|
bool CMyOpenCL::BufferWrite(const int buffer_index, MATRIX &data, const uint cl_buffer_offset)
|
|
{
|
|
//--- check parameters
|
|
if(buffer_index < 0 || buffer_index >= m_buffers_total || data.Rows() <= 0)
|
|
return(false);
|
|
if(m_buffers[buffer_index] == INVALID_HANDLE)
|
|
return(false);
|
|
if(m_context == INVALID_HANDLE || m_program == INVALID_HANDLE)
|
|
return(false);
|
|
//--- write data to OpenCL buffer
|
|
if(!CLBufferWrite(m_buffers[buffer_index], cl_buffer_offset, data))
|
|
return(false);
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|