NeuroBook/Include/realization/buffer.mqh
super.admin 951d788cd9 convert
2025-05-30 16:12:30 +02:00

486 lines
37 KiB
MQL5

//+------------------------------------------------------------------+
//| BufferDouble.mqh |
//| Copyright 2021, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Connect libraries |
//+------------------------------------------------------------------+
#include <Arrays\Array.mqh>
#include "opencl.mqh"
//+------------------------------------------------------------------+
//| Class CBufferType |
//| Purpose: Dynamic data buffer class |
//+------------------------------------------------------------------+
class CBufferType: public CObject
{
protected:
CMyOpenCL* m_cOpenCL; // OpenCL context object
int m_myIndex; // data buffer index in context
public:
CBufferType(void);
~CBufferType(void);
//---
MATRIX m_mMatrix;
//--- method for initializing the buffer with initial values
virtual bool BufferInit(const ulong rows, const ulong columns, const TYPE value = 0);
//--- create a new buffer in the OpenCL context
virtual bool BufferCreate(CMyOpenCL *opencl);
//--- delete a buffer in the OpenCL context
virtual bool BufferFree(void);
//--- read data of the buffer from the OpenCL context
virtual bool BufferRead(void);
//--- write buffer data to the OpenCL context
virtual bool BufferWrite(void);
//--- get buffer index
virtual int GetIndex(void);
//--- change buffer index
virtual bool SetIndex(int index)
{
if(!m_cOpenCL.BufferFree(m_myIndex))
return false;
m_myIndex = index;
return true;
}
//--- copy buffer data to the array
virtual int GetData(TYPE &values[], bool load = true);
virtual int GetData(MATRIX &values, bool load = true);
virtual int GetData(CBufferType *values, bool load = true);
//--- calculate the average value of the data buffer
virtual TYPE MathMean(void);
//--- vector operations
virtual bool SumArray(CBufferType *src);
virtual int Scaling(TYPE value);
virtual bool Split(CBufferType* target1, CBufferType* target2, const int position);
virtual bool Concatenate(CBufferType* target1, CBufferType* target2, const ulong positions1, const ulong positions2);
//--- file handling methods
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- class identifier
virtual int Type(void) const { return defBuffer; }
ulong Rows(void) const { return m_mMatrix.Rows(); }
ulong Cols(void) const { return m_mMatrix.Cols(); }
ulong Total(void) const { return (m_mMatrix.Rows() * m_mMatrix.Cols()); }
TYPE At(uint index) const { return m_mMatrix.Flat(index); }
TYPE operator[](ulong index) const { return m_mMatrix.Flat(index); }
VECTOR Row(ulong row) { return m_mMatrix.Row(row); }
VECTOR Col(ulong col) { return m_mMatrix.Col(col); }
bool Row(VECTOR& vec, ulong row) { return m_mMatrix.Row(vec, row); }
bool Col(VECTOR& vec, ulong col) { return m_mMatrix.Col(vec, col); }
bool Activation(MATRIX& mat_out, ENUM_ACTIVATION_FUNCTION func) { return m_mMatrix.Activation(mat_out, func);}
bool Derivative(MATRIX& mat_out, ENUM_ACTIVATION_FUNCTION func) { return m_mMatrix.Derivative(mat_out, func);}
bool Reshape(ulong rows, ulong cols){ return m_mMatrix.Reshape(rows, cols); }
bool Update(uint index, TYPE value)
{
if(index >= Total())
return false;
m_mMatrix.Flat(index, value);
return true;
}
bool Update(uint row, uint col, TYPE value)
{
if(row >= Rows() || col >= Cols())
return false;
m_mMatrix[row, col] = value;
return true;
}
};
//+------------------------------------------------------------------+
//| Class constructor |
//+------------------------------------------------------------------+
CBufferType::CBufferType(void) : m_myIndex(-1)
{
m_cOpenCL = NULL;
}
//+------------------------------------------------------------------+
//| Class destructor |
//+------------------------------------------------------------------+
CBufferType::~CBufferType(void)
{
if(m_cOpenCL && m_myIndex >= 0)
{
if(m_cOpenCL.BufferFree(m_myIndex))
{
m_myIndex = -1;
m_cOpenCL = NULL;
}
}
}
//+------------------------------------------------------------------+
//| Creating a new buffer in the OpenCL context |
//+------------------------------------------------------------------+
bool CBufferType::BufferCreate(CMyOpenCL *opencl)
{
//--- source data checking bock
if(!opencl)
{
BufferFree();
return false;
}
//--- if the received pointer matches the previously saved one, copy the buffer contents to the context memory
if(opencl == m_cOpenCL && m_myIndex >= 0)
return BufferWrite();
//--- check the presence of a previously saved pointer to OpenCL context
//--- if present, delete the buffer from the unused context
if(m_cOpenCL && m_myIndex >= 0)
{
if(m_cOpenCL.BufferFree(m_myIndex))
{
m_myIndex = -1;
m_cOpenCL = NULL;
}
else
return false;
}
//--- create a new buffer in the specified OpenCL context
if((m_myIndex = opencl.AddBufferFromArray(m_mMatrix, 0, CL_MEM_READ_WRITE)) < 0)
return false;
m_cOpenCL = opencl;
//---
return true;
}
//+------------------------------------------------------------------+
//| Method for removing the buffer from the OpenCL context |
//+------------------------------------------------------------------+
bool CBufferType::BufferFree(void)
{
//--- check the presence of a previously saved pointer to OpenCL context
//--- if present, delete the buffer from the unused context
if(m_cOpenCL && m_myIndex >= 0)
if(m_cOpenCL.BufferFree(m_myIndex))
{
m_myIndex = -1;
m_cOpenCL = NULL;
return true;
}
if(m_myIndex >= 0)
m_myIndex = -1;
//---
return false;
}
//+------------------------------------------------------------------+
//| Method for reading data from the buffer in the OpenCL context |
//+------------------------------------------------------------------+
bool CBufferType::BufferRead(void)
{
if(!m_cOpenCL || m_myIndex < 0)
return false;
//---
return m_cOpenCL.BufferRead(m_myIndex, m_mMatrix, 0);
}
//+------------------------------------------------------------------+
//| Method for writing data to the buffer in the OpenCL context |
//+------------------------------------------------------------------+
bool CBufferType::BufferWrite(void)
{
if(!m_cOpenCL || m_myIndex < 0)
return false;
//---
return m_cOpenCL.BufferWrite(m_myIndex, m_mMatrix, 0);
}
//+------------------------------------------------------------------+
//| Method for initializing the buffer with initial values |
//+------------------------------------------------------------------+
bool CBufferType::BufferInit(ulong rows, ulong columns, TYPE value)
{
if(rows <= 0 || columns <= 0)
return false;
//---
m_mMatrix = MATRIX::Full(rows, columns, value);
if(m_cOpenCL)
{
CMyOpenCL *opencl=m_cOpenCL;
BufferFree();
return BufferCreate(opencl);
}
//---
return true;
}
//+------------------------------------------------------------------+
//| Method for getting buffer values |
//+------------------------------------------------------------------+
int CBufferType::GetData(TYPE &values[], bool load = true)
{
if(load && !BufferRead())
return -1;
if(ArraySize(values) != Total() &&
ArrayResize(values, (uint)Total()) <= 0)
return false;
//---
for(uint i = 0; i < Total(); i++)
values[i] = m_mMatrix.Flat(i);
return (int)Total();
}
//+------------------------------------------------------------------+
//| Method for getting buffer values |
//+------------------------------------------------------------------+
int CBufferType::GetData(MATRIX &values, bool load = true)
{
if(load && !BufferRead())
return -1;
//---
values = m_mMatrix;
return (int)Total();
}
//+------------------------------------------------------------------+
//| Method for getting buffer values |
//+------------------------------------------------------------------+
int CBufferType::GetData(CBufferType *values, bool load = true)
{
if(!values)
return -1;
if(load && !BufferRead())
return -1;
values.m_mMatrix.Copy(m_mMatrix);
return (int)values.Total();
}
//+------------------------------------------------------------------+
//| Method for summing up elements of two data buffers |
//+------------------------------------------------------------------+
bool CBufferType::SumArray(CBufferType *src)
{
//--- check source data array
if(!src || src.Total() != Total())
return(false);
//---
if(!m_cOpenCL)
{
//--- resizing the matrix
MATRIX temp = src.m_mMatrix;
if(!temp.Reshape(Rows(), Cols()))
return(false);
//--- adding matrices
m_mMatrix += temp;
}
else
{
if(src.GetIndex() < 0 && !BufferCreate(m_cOpenCL))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Sum, def_sum_inputs1, m_myIndex))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Sum, def_sum_inputs2, src.GetIndex()))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Sum, def_sum_outputs, m_myIndex))
return false;
uint off_set[] = {0};
uint NDRange[] = {(uint)Total()};
if(!m_cOpenCL.Execute(def_k_Sum, 1, off_set, NDRange))
return false;
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Method for computing the average value of the array |
//+------------------------------------------------------------------+
TYPE CBufferType::MathMean(void)
{
return m_mMatrix.Mean();
}
//+------------------------------------------------------------------+
//| Get the index of the buffer in the OpenCL context |
//+------------------------------------------------------------------+
int CBufferType::GetIndex(void)
{
if(!m_cOpenCL || m_myIndex < 0)
{
m_myIndex = -1;
m_cOpenCL = NULL;
return m_myIndex;
}
//---
if(!m_cOpenCL.CheckBuffer(m_myIndex))
m_myIndex = BufferCreate(m_cOpenCL);
//---
return m_myIndex;
}
//+------------------------------------------------------------------+
//| Data scaling method (multiplying by a constant) |
//+------------------------------------------------------------------+
int CBufferType::Scaling(TYPE value)
{
if(!m_cOpenCL)
m_mMatrix *= value;
else
{
if(m_myIndex <= 0)
return false;
//--- pass parameters to the kernel
if(!m_cOpenCL.SetArgumentBuffer(def_k_LineActivation, def_activ_inputs, m_myIndex))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_LineActivation, def_activ_outputs, m_myIndex))
return false;
if(!m_cOpenCL.SetArgument(def_k_LineActivation, def_activ_param_a, value))
return false;
if(!m_cOpenCL.SetArgument(def_k_LineActivation, def_activ_param_b, 0))
return false;
//--- place kernel to the execution queue
int off_set[] = {0};
int NDRange[] = { (int)Total() };
if(!m_cOpenCL.Execute(def_k_LineActivation, 1, off_set, NDRange))
return false;
}
//---
return (int)Total();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferType::Save(const int file_handle)
{
if(file_handle == INVALID_HANDLE)
return false;
if(m_myIndex >= 0)
if(!BufferRead())
return false;
//---
if(FileWriteInteger(file_handle, Type()) < INT_VALUE)
return false;
if(FileWriteLong(file_handle, Rows()) < sizeof(long))
return false;
if(FileWriteLong(file_handle, Cols()) < sizeof(long))
return false;
//---
for(ulong r = 0; r < Rows(); r++)
for(ulong c = 0; c < Cols(); c++)
if(FileWriteDouble(file_handle, m_mMatrix[r, c]) < sizeof(double))
return false;
//---
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferType::Load(const int file_handle)
{
if(file_handle == INVALID_HANDLE)
return false;
if(FileReadInteger(file_handle) != Type())
return false;
//---
ulong rows = FileReadLong(file_handle);
ulong cols = FileReadLong(file_handle);
if(!m_mMatrix.Init(rows, cols))
return false;
for(ulong r = 0; r < rows; r++)
for(ulong c = 0; c < cols; c++)
m_mMatrix[r, c] = (TYPE)FileReadDouble(file_handle);
//---
if(m_myIndex >= 0)
{
if(!BufferFree())
return false;
if(!BufferCreate(m_cOpenCL))
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferType::Split(CBufferType *target1, CBufferType *target2, const int position)
{
if(!target1 || !target2)
return false;
//---
if(!m_cOpenCL)
{
ulong split[] = {position};
MATRIX m[];
if(!m_mMatrix.Vsplit(split, m))
return false;
if(target1!=GetPointer(this))
target1.m_mMatrix = m[0];
target2.m_mMatrix = m[1];
}
else
{
if((int)target1.Total() < position)
return false;
if(target1.GetIndex() < 0 && !target1.BufferCreate(m_cOpenCL))
return false;
if(target2.GetIndex() < 0 && !target2.BufferCreate(m_cOpenCL))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Split, def_split_source, m_myIndex))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Split, def_split_target1, target1.GetIndex()))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Split, def_split_target2, target2.GetIndex()))
return false;
if(!m_cOpenCL.SetArgument(def_k_Split, def_split_total_source, (int)Total()))
return false;
if(!m_cOpenCL.SetArgument(def_k_Split, def_split_total_target1, position))
return false;
if(!m_cOpenCL.SetArgument(def_k_Split, def_split_total_target2, (int)target2.Total()))
return false;
//--- place kernel to the execution queue
int off_set[] = {0};
int NDRange[] = {(int)Total()};
ResetLastError();
if(!m_cOpenCL.Execute(def_k_Split, 1, off_set, NDRange))
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferType::Concatenate(CBufferType *source1, CBufferType *source2, const ulong positions1, const ulong positions2)
{
if(!source1 || source1.Total() < positions1)
return false;
if(!source2 || source2.Total() < positions2)
return false;
//---
if(!m_cOpenCL)
{
m_mMatrix = source1.m_mMatrix;
if(!m_mMatrix.Resize(m_mMatrix.Rows(), positions1 + positions2))
return false;
for(ulong c = 0; c < positions2; c++)
if(!m_mMatrix.Col(source2.m_mMatrix.Col(c), positions1 + c))
return false;
}
else
{
if(source1.Total() < positions1)
return false;
if(source2.Total() < positions2)
return false;
if(Total() < positions1 + positions2)
return false;
if(source1.GetIndex() < 0 && !source1.BufferCreate(m_cOpenCL))
return false;
if(source2.GetIndex() < 0 && !source2.BufferCreate(m_cOpenCL))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Concatenate, def_concat_source1, source1.GetIndex()))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Concatenate, def_concat_source2, source2.GetIndex()))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_Concatenate, def_concat_target, m_myIndex))
return false;
if(!m_cOpenCL.SetArgument(def_k_Concatenate, def_concat_total_target, (int)Total()))
return false;
if(!m_cOpenCL.SetArgument(def_k_Concatenate, def_concat_total_source1, (int)positions1))
return false;
if(!m_cOpenCL.SetArgument(def_k_Concatenate, def_concat_total_sourse2, (int)positions2))
return false;
//--- place kernel to the execution queue
int off_set[] = {0};
int NDRange[] = {(int)Total()};
ResetLastError();
if(!m_cOpenCL.Execute(def_k_Concatenate, 1, off_set, NDRange))
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+