2026-09-15 22:45:34 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| StdCL.mqh |
|
| | | //| Copyright 2026, Niquel Mendoza. |
|
| | | //| https://www.mql5.com |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2026, Niquel Mendoza."
|
| | | #property link "https://www.mql5.com"
|
| | | #property strict
|
| | |
|
| | |
|
2026-09-16 10:10:34 -05:00 | | | #ifndef SCALERBYLEO_SRC_SCALER_STD_STDCL_MQH
|
| | | #define SCALERBYLEO_SRC_SCALER_STD_STDCL_MQH
|
2026-09-15 22:45:34 -05:00 | | |
|
2026-09-16 08:06:10 -05:00 | | |
|
2026-09-15 22:45:34 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #include "StdBase.mqh"
|
| | | #include "..\\..\\CL\\Main.mqh"
|
| | |
|
2026-09-16 08:06:10 -05:00 | | |
|
2026-09-15 22:45:34 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-16 18:51:57 -05:00 | | | //--- kernel transform / inverse (mismo layout de args en ambos kernels)
|
2026-09-15 22:45:34 -05:00 | | | #define SCALERBYLEO_STDCL_TRANSFORM_IDX_MEAN (0)
|
| | | #define SCALERBYLEO_STDCL_TRANSFORM_IDX_STDINV (1)
|
2026-09-16 18:51:57 -05:00 | | | #define SCALERBYLEO_STDCL_TRANSFORM_IDX_STD (1)
|
2026-09-15 22:45:34 -05:00 | | | #define SCALERBYLEO_STDCL_TRANSFORM_IDX_MATRIX (2)
|
| | | #define SCALERBYLEO_STDCL_TRANSFORM_IDX_COLS (3)
|
2026-09-16 18:51:57 -05:00 | | | #define SCALERBYLEO_STDCL_TRANSFORM_IDX_ISTART (4)
|
2026-09-15 22:45:34 -05:00 | | |
|
| | | //---
|
| | | #define SCALERBYLEO_STDCL_KNAME_TRANSFORM ("standard_scaler_tranform_matrix")
|
| | | #define SCALERBYLEO_STDCL_KNAME_INV_TRANSFORM ("standard_scaler_inverse_tranform_matrix")
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | template<typename TFlt>
|
| | | class StandardizationScalerCL : public StandardizationScalerBase<TFlt>
|
| | | {
|
| | | private:
|
2026-09-16 08:06:10 -05:00 | | | bool OnLoad() override final;
|
2026-09-15 22:45:34 -05:00 | | |
|
| | | //---
|
| | | int m_buffer_h_mean;
|
| | | int m_buffer_h_std_inv;
|
| | | int m_buffer_h_std;
|
| | |
|
| | | //---
|
| | | int m_kernel_transform;
|
| | | int m_kernel_inv_transform;
|
| | |
|
2026-09-16 08:06:10 -05:00 | | | //---
|
| | | bool m_is_init;
|
| | |
|
2026-09-15 22:45:34 -05:00 | | |
|
| | | public:
|
| | | StandardizationScalerCL(void);
|
| | | ~StandardizationScalerCL(void) {}
|
| | |
|
| | | //---
|
2026-09-16 18:51:57 -05:00 | | | __forceinline bool FitTransform(matrix<TFlt> &X, matrix<TFlt> &out);
|
| | | bool Transform(matrix<TFlt> &X, matrix<TFlt> &out);
|
| | | bool InverseTransform(matrix<TFlt> &X_scaled, matrix<TFlt> &out);
|
2026-09-15 22:45:34 -05:00 | | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-16 08:06:10 -05:00 | | | template<typename TFlt> StandardizationScalerCL::StandardizationScalerCL()
|
| | | : m_buffer_h_mean(INVALID_HANDLE), m_buffer_h_std_inv(INVALID_HANDLE), m_buffer_h_std(INVALID_HANDLE),
|
| | | m_kernel_transform(INVALID_HANDLE), m_kernel_inv_transform(INVALID_HANDLE), m_is_init(false)
|
2026-09-15 22:45:34 -05:00 | | | {
|
2026-09-16 10:10:34 -05:00 | | | m_type = SCALERBYLEO_SCALER_TYPE_STANDART_CL;
|
2026-09-15 22:45:34 -05:00 | | | }
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | template<typename TFlt>
|
2026-09-16 08:06:10 -05:00 | | | bool StandardizationScalerCL::OnLoad()
|
2026-09-15 22:45:34 -05:00 | | | {
|
2026-09-16 08:06:10 -05:00 | | | //---
|
| | | if(!m_is_init)
|
| | | {
|
| | | //---
|
| | | MQLART_TRY_INI
|
| | |
|
| | | //---
|
| | | if(sizeof(TFlt) == sizeof(float))
|
| | | {
|
2026-09-16 18:20:12 -05:00 | | | MQLART_TRY(COpenCLCtxManager<TFlt>::ProgramInit(g_cl_scaler_program_flt), true)
|
2026-09-16 08:06:10 -05:00 | | | }
|
| | | else
|
| | | {
|
2026-09-16 18:20:12 -05:00 | | | MQLART_TRY(COpenCLCtxManager<TFlt>::ProgramInit(g_cl_scaler_program_dbl), true)
|
2026-09-16 08:06:10 -05:00 | | | }
|
| | |
|
| | | //---
|
2026-09-16 18:20:12 -05:00 | | | MQLART_TRY(COpenCLCtxManager<TFlt>::KernelGet(SCALERBYLEO_STDCL_KNAME_TRANSFORM, m_kernel_transform), true)
|
| | | MQLART_TRY(COpenCLCtxManager<TFlt>::KernelGet(SCALERBYLEO_STDCL_KNAME_INV_TRANSFORM, m_kernel_inv_transform), true)
|
2026-09-16 08:06:10 -05:00 | | |
|
| | | //---
|
| | | m_is_init = true;
|
| | |
|
| | | //---
|
| | | MQLART_TRY_END
|
| | |
|
| | | //---
|
| | | if(MQLART_TRY_IS_ERR)
|
| | | {
|
| | | m_last_err = SCALERBYLEO_ERR_IN_CTX_MANAGER_CL;
|
| | | return false;
|
| | | }
|
| | | }
|
| | |
|
2026-09-15 22:45:34 -05:00 | | | //--- actulizamos los 3 buffers
|
| | | OPENCLMANAGER_MAKE_VECTOR(m_buffer_h_std, m_std, CL_MEM_READ_ONLY)
|
| | | OPENCLMANAGER_MAKE_VECTOR(m_buffer_h_mean, m_mean, CL_MEM_READ_ONLY)
|
| | | OPENCLMANAGER_MAKE_VECTOR(m_buffer_h_std_inv, m_std_inv, CL_MEM_READ_ONLY)
|
| | | return true; // exito
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | template<typename TFlt>
|
2026-09-16 18:51:57 -05:00 | | | __forceinline bool StandardizationScalerCL::FitTransform(matrix<TFlt> &X, matrix<TFlt> &out)
|
2026-09-15 22:45:34 -05:00 | | | {
|
| | | //---
|
| | | if(!Fit(X))
|
| | | return false;
|
| | | if(!Transform(X, out))
|
| | | return false;
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Transform |
|
| | | //+------------------------------------------------------------------+
|
| | | template<typename TFlt>
|
2026-09-16 18:51:57 -05:00 | | | bool StandardizationScalerCL::Transform(matrix<TFlt> &X, matrix<TFlt> &out)
|
2026-09-15 22:45:34 -05:00 | | | {
|
| | | //---
|
| | | if(!m_loaded_scaler)
|
| | | {
|
| | | m_last_err = SCALERBYLEO_ERR_NOT_TRAINED;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //--- chekeo de rows
|
| | | const ulong rows = X.Rows();
|
| | | if(rows == 0)
|
| | | {
|
| | | m_last_err = SCALERBYLEO_ERR_EMPTY_INPUT;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //--- chekeo de cols
|
| | | const ulong total_cols = X.Cols();
|
2026-09-16 18:51:57 -05:00 | | | const ulong fs = m_mean.Size();
|
2026-09-15 22:45:34 -05:00 | | | if(m_i_start + fs > total_cols)
|
| | | {
|
| | | m_last_err = SCALERBYLEO_ERR_SIZE_MISMATCH;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //--- init
|
| | | int matrix_h = INVALID_HANDLE;
|
| | | ::ResetLastError();
|
| | |
|
| | | //---
|
| | | MQLART_TRY_INI
|
| | |
|
2026-09-16 18:51:57 -05:00 | | | //--- Decidimos que subimos a la GPU segun el caso (patron validado en Bench/CLPattern.mq5)
|
| | | ulong istart, cl_cols;
|
| | | if(m_reconstruir && fs != total_cols)
|
| | | {
|
| | | //--- Caso ambiguo: subimos TODO + offset (Estrategia A, gano el benchmark)
|
| | | out.Resize(rows, total_cols);
|
| | | istart = m_i_start;
|
| | | cl_cols = total_cols;
|
| | |
|
| | | const uint write = uint(sizeof(TFlt) * total_cols * rows);
|
| | | matrix_h = CLBufferCreate(CCLCtxShared::s_context, write, CL_MEM_READ_WRITE);
|
| | | MQLART_TRY_NOT(matrix_h, INVALID_HANDLE)
|
| | | MQLART_TRY(CLBufferWrite(matrix_h, 0, X), true)
|
| | | }
|
| | | else
|
| | | {
|
| | | istart = 0;
|
| | |
|
| | | if(fs == total_cols)
|
| | | {
|
| | | //--- Caso trivial: se escala todo, no hay nada que reconstruir
|
| | | out.Resize(rows, total_cols);
|
| | | cl_cols = total_cols;
|
| | |
|
| | | const uint write = uint(sizeof(TFlt) * total_cols * rows);
|
| | | matrix_h = CLBufferCreate(CCLCtxShared::s_context, write, CL_MEM_READ_WRITE);
|
| | | MQLART_TRY_NOT(matrix_h, INVALID_HANDLE)
|
| | | MQLART_TRY(CLBufferWrite(matrix_h, 0, X), true)
|
| | | }
|
| | | else
|
| | | {
|
| | | //--- Caso !reconstruir: solo interesa el rango, subimos angosto
|
| | | out.Resize(rows, fs);
|
| | | cl_cols = fs;
|
| | |
|
| | | matrix<TFlt> in(rows, fs);
|
| | | for(ulong c = 0; c < fs; c++)
|
| | | for(ulong r = 0; r < rows; r++)
|
| | | in[r][c] = X[r][m_i_start + c];
|
| | |
|
| | | const uint write = uint(sizeof(TFlt) * fs * rows);
|
| | | matrix_h = CLBufferCreate(CCLCtxShared::s_context, write, CL_MEM_READ_WRITE);
|
| | | MQLART_TRY_NOT(matrix_h, INVALID_HANDLE)
|
| | | MQLART_TRY(CLBufferWrite(matrix_h, 0, in), true)
|
| | | }
|
| | | }
|
2026-09-15 22:45:34 -05:00 | | |
|
| | | //---
|
| | | MQLART_TRY(CLSetKernelArgMem(m_kernel_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_MEAN, m_buffer_h_mean), true)
|
| | | MQLART_TRY(CLSetKernelArgMem(m_kernel_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_STDINV, m_buffer_h_std_inv), true)
|
| | | MQLART_TRY(CLSetKernelArgMem(m_kernel_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_MATRIX, matrix_h), true)
|
2026-09-16 18:51:57 -05:00 | | | MQLART_TRY(CLSetKernelArg(m_kernel_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_COLS, uint(cl_cols)), true)
|
| | | MQLART_TRY(CLSetKernelArg(m_kernel_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_ISTART, uint(istart)), true)
|
2026-09-15 22:45:34 -05:00 | | |
|
| | | //---
|
| | | const uint work_off_set[2] = {0, 0};
|
| | | uint work_size_tranfors[2] = { (uint)rows, (uint)fs };
|
| | | MQLART_TRY(CLExecute(m_kernel_transform, 2, work_off_set, work_size_tranfors), true)
|
| | | CLBufferRead(matrix_h, 0, out);
|
| | |
|
| | | //---
|
| | | MQLART_TRY_END
|
| | |
|
| | | //---
|
| | | if(matrix_h != INVALID_HANDLE)
|
| | | CLBufferFree(matrix_h);
|
| | |
|
| | | //---
|
| | | if(MQLART_TRY_IS_ERR)
|
| | | {
|
| | | m_last_err = SCALERBYLEO_ERR_IN_OPENCL;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| InverseTransform |
|
| | | //+------------------------------------------------------------------+
|
| | | template<typename TFlt>
|
2026-09-16 18:51:57 -05:00 | | | bool StandardizationScalerCL::InverseTransform(matrix<TFlt> &X_scaled, matrix<TFlt> &out)
|
2026-09-15 22:45:34 -05:00 | | | {
|
| | | //---
|
| | | if(!m_loaded_scaler)
|
| | | {
|
| | | m_last_err = SCALERBYLEO_ERR_NOT_TRAINED;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //--- chekeo de rows
|
| | | const ulong rows = X_scaled.Rows();
|
| | | if(rows == 0)
|
| | | {
|
| | | m_last_err = SCALERBYLEO_ERR_EMPTY_INPUT;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //--- chekeo de cols
|
| | | const ulong total_cols = X_scaled.Cols();
|
| | | const ulong fs = m_mean.Size();
|
| | | if(m_i_start + fs > total_cols)
|
| | | {
|
| | | m_last_err = SCALERBYLEO_ERR_SIZE_MISMATCH;
|
| | | return false;
|
| | | }
|
| | |
|
2026-09-16 08:06:10 -05:00 | | | //--- init
|
| | | int matrix_h = INVALID_HANDLE;
|
| | | ::ResetLastError();
|
| | |
|
| | | //---
|
| | | MQLART_TRY_INI
|
| | |
|
| | | //---
|
2026-09-16 18:51:57 -05:00 | | | ulong istart, cl_cols;
|
| | | if(m_reconstruir && fs != total_cols)
|
| | | {
|
| | | out.Resize(rows, total_cols);
|
| | | istart = m_i_start;
|
| | | cl_cols = total_cols;
|
| | |
|
| | | const uint write = uint(sizeof(TFlt) * total_cols * rows);
|
| | | matrix_h = CLBufferCreate(CCLCtxShared::s_context, write, CL_MEM_READ_WRITE);
|
| | | MQLART_TRY_NOT(matrix_h, INVALID_HANDLE)
|
| | | MQLART_TRY(CLBufferWrite(matrix_h, 0, X_scaled), true)
|
| | | }
|
| | | else
|
| | | {
|
| | | istart = 0;
|
| | |
|
| | | if(fs == total_cols)
|
| | | {
|
| | | out.Resize(rows, total_cols);
|
| | | cl_cols = total_cols;
|
| | |
|
| | | const uint write = uint(sizeof(TFlt) * total_cols * rows);
|
| | | matrix_h = CLBufferCreate(CCLCtxShared::s_context, write, CL_MEM_READ_WRITE);
|
| | | MQLART_TRY_NOT(matrix_h, INVALID_HANDLE)
|
| | | MQLART_TRY(CLBufferWrite(matrix_h, 0, X_scaled), true)
|
| | | }
|
| | | else
|
| | | {
|
| | | out.Resize(rows, fs);
|
| | | cl_cols = fs;
|
| | |
|
| | | matrix<TFlt> in(rows, fs);
|
| | | for(ulong c = 0; c < fs; c++)
|
| | | for(ulong r = 0; r < rows; r++)
|
| | | in[r][c] = X_scaled[r][m_i_start + c];
|
| | |
|
| | | const uint write = uint(sizeof(TFlt) * fs * rows);
|
| | | matrix_h = CLBufferCreate(CCLCtxShared::s_context, write, CL_MEM_READ_WRITE);
|
| | | MQLART_TRY_NOT(matrix_h, INVALID_HANDLE)
|
| | | MQLART_TRY(CLBufferWrite(matrix_h, 0, in), true)
|
| | | }
|
| | | }
|
2026-09-16 08:06:10 -05:00 | | |
|
| | | //---
|
| | | MQLART_TRY(CLSetKernelArgMem(m_kernel_inv_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_MEAN, m_buffer_h_mean), true)
|
| | | MQLART_TRY(CLSetKernelArgMem(m_kernel_inv_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_STD, m_buffer_h_std), true)
|
| | | MQLART_TRY(CLSetKernelArgMem(m_kernel_inv_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_MATRIX, matrix_h), true)
|
2026-09-16 18:51:57 -05:00 | | | MQLART_TRY(CLSetKernelArg(m_kernel_inv_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_COLS, uint(cl_cols)), true)
|
| | | MQLART_TRY(CLSetKernelArg(m_kernel_inv_transform, SCALERBYLEO_STDCL_TRANSFORM_IDX_ISTART, uint(istart)), true)
|
2026-09-16 08:06:10 -05:00 | | |
|
| | | //---
|
| | | const uint work_off_set[2] = {0, 0};
|
| | | uint work_size_tranfors[2] = { (uint)rows, (uint)fs };
|
| | | MQLART_TRY(CLExecute(m_kernel_inv_transform, 2, work_off_set, work_size_tranfors), true)
|
| | | CLBufferRead(matrix_h, 0, out);
|
| | |
|
| | | //---
|
| | | MQLART_TRY_END
|
| | |
|
| | | //---
|
| | | if(matrix_h != INVALID_HANDLE)
|
| | | CLBufferFree(matrix_h);
|
| | |
|
| | | //---
|
| | | if(MQLART_TRY_IS_ERR)
|
2026-09-15 22:45:34 -05:00 | | | {
|
2026-09-16 08:06:10 -05:00 | | | m_last_err = SCALERBYLEO_ERR_IN_OPENCL;
|
| | | return false;
|
2026-09-15 22:45:34 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | }
|
| | |
|
| | |
|
2026-09-16 10:10:34 -05:00 | | | #endif // SCALERBYLEO_SRC_SCALER_STD_STDCL_MQH
|