ScalerByLeo/Src/Scaler/Bench/OpMatrixIsFastOrNot.mq5
nique_372 1496207a00 mejoras
2026-09-16 18:20:12 -05:00

137 lines
No EOL
5 KiB
MQL5

//+------------------------------------------------------------------+
//| BenchCopyApproach.mq5 |
//| Compara DOS formas de producir una matriz "modificada en una |
//| region, resto intacto", SIN OpenCL, SIN min-max, solo para medir |
//| el costo puro de la estrategia de copia. |
//| |
//| a) out = X; luego se sobreescribe solo la region [st, st+fs) |
//| b) out.Resize(...); loops manuales: copia region "alta" (0..st), |
//| escribe la region modificada, copia region "baja" (st+fs..N) |
//| |
//| La "modificacion" es trivial (val*2+1) a proposito: no queremos |
//| medir el costo del scaler, solo el costo de la estrategia de copia|
//+------------------------------------------------------------------+
#property script_show_inputs
//+------------------------------------------------------------------+
int g_sizes[] = {500, 2000, 5000}; // rows == total_cols
double g_fs_fracs[] = {0.01, 0.10, 0.50, 0.90, 1.00};
int g_repeats = 7; // repeticiones, se reporta la mediana
//+------------------------------------------------------------------+
//| A) out = X (copia completa) + overwrite solo de la region |
//+------------------------------------------------------------------+
ulong RunOnce_A(matrix<float> &X, const ulong st, const ulong fs)
{
const ulong t0 = GetMicrosecondCount();
matrix<float> out = X;
for(ulong c = 0; c < fs; c++)
for(ulong r = 0; r < X.Rows(); r++)
out[r][st + c] = X[r][st + c] * 2.0f + 1.0f;
return GetMicrosecondCount() - t0;
}
//+------------------------------------------------------------------+
//| B) loops manuales: copia region alta, escribe modificada, copia |
//| region baja. (tal como el patron original del reconstruir) |
//+------------------------------------------------------------------+
ulong RunOnce_B(matrix<float> &X, const ulong st, const ulong fs)
{
const ulong rows = X.Rows();
const ulong total_cols = X.Cols();
const ulong t0 = GetMicrosecondCount();
matrix<float> out(rows, total_cols);
ulong c = 0;
for(; c < st; c++)
for(ulong r = 0; r < rows; r++)
out[r][c] = X[r][c];
const ulong mid_end = st + fs;
for(; c < mid_end; c++)
for(ulong r = 0; r < rows; r++)
out[r][c] = X[r][c] * 2.0f + 1.0f;
for(; c < total_cols; c++)
for(ulong r = 0; r < rows; r++)
out[r][c] = X[r][c];
return GetMicrosecondCount() - t0;
}
//+------------------------------------------------------------------+
//| C) control: SOLO out = X, nada más (para aislar cuánto cuesta |
//| el operator= por sí solo, sin overwrite encima) |
//+------------------------------------------------------------------+
ulong RunOnce_C_OnlyAssign(matrix<float> &X)
{
matrix<float> out;
const ulong t0 = GetMicrosecondCount();
out = X;
return GetMicrosecondCount() - t0;
}
//+------------------------------------------------------------------+
ulong Median(ulong &arr[])
{
const int n = ArraySize(arr);
ArraySort(arr);
return arr[n / 2];
}
//+------------------------------------------------------------------+
void OnStart()
{
Print("=== Bench: estrategia de copia (out=X+overwrite vs loops manuales) ===");
PrintFormat("%-6s %-6s %-6s %-12s %-12s %-12s %-10s",
"size", "fs", "frac", "A(us)", "B(us)", "OnlyAssign", "A_vs_B");
for(int si = 0; si < ArraySize(g_sizes); si++)
{
const int size = g_sizes[si];
matrix<float> X;
X.Resize(size, size);
X.Random(0.0, 20.0);
ulong assign_t[];
ArrayResize(assign_t, g_repeats);
for(int rep = 0; rep < g_repeats; rep++)
assign_t[rep] = RunOnce_C_OnlyAssign(X);
const ulong assign_med = Median(assign_t);
for(int fi = 0; fi < ArraySize(g_fs_fracs); fi++)
{
ulong fs = (ulong)MathMax(1, MathRound(size * g_fs_fracs[fi]));
if(fs > (ulong)size) fs = size;
const ulong st = 0; // region siempre arranca en 0, simplificamos
ulong a_t[], b_t[];
ArrayResize(a_t, g_repeats);
ArrayResize(b_t, g_repeats);
for(int rep = 0; rep < g_repeats; rep++)
{
a_t[rep] = RunOnce_A(X, st, fs);
b_t[rep] = RunOnce_B(X, st, fs);
}
const ulong a_med = Median(a_t);
const ulong b_med = Median(b_t);
const double ratio = (a_med > 0) ? (double)b_med / (double)a_med : 0.0;
PrintFormat("%-6d %-6d %-6.2f %-12I64u %-12I64u %-12I64u %-10.2f",
size, fs, g_fs_fracs[fi], a_med, b_med, assign_med, ratio);
}
}
Print("=== Fin ===");
Print("A_vs_B > 1.0 significa que B (loops manuales) fue MAS RAPIDO que A (out=X+overwrite)");
Print("A_vs_B < 1.0 significa que A (out=X+overwrite) fue MAS RAPIDO que B");
Print("OnlyAssign muestra el costo puro de 'out = X' sin ningun overwrite encima, para referencia");
}
//+------------------------------------------------------------------+