//+------------------------------------------------------------------+ //| 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 &X, const ulong st, const ulong fs) { const ulong t0 = GetMicrosecondCount(); matrix 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 &X, const ulong st, const ulong fs) { const ulong rows = X.Rows(); const ulong total_cols = X.Cols(); const ulong t0 = GetMicrosecondCount(); matrix 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 &X) { matrix 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 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"); } //+------------------------------------------------------------------+