137 lines
No EOL
5 KiB
MQL5
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");
|
|
}
|
|
//+------------------------------------------------------------------+ |