Hola,
Actualizo el hilo. He estado codificando un sistema a modo de prueba. Y hasta el momento solo he estado probando el método tradicional (SetLength) consiguiendo unos resultados bastante optimistas, pero no quisiera aventurarme demasiado.
Luego he estado llevando la codificación con el método GetMem/FreeMem. Al probar mi código algo falla.

Recibo unos avisos de error al finalizar el programa, primero un AccessViolation en la dirección 00C4FFFC y finalmente un Runtime Error 216 at 004034BA.
Esto es cuando cierro el programa e intento correr la prueba basada en GetMem. Con el método tradicional no hay problemas.
La verdad es que ando desconcertado... porque poniendo breackpoint en mi código todo parece andar perfecto.
Primeramente con una traza había detectado que la falla estaba en el Finalize(), lo comenté y dejé en FreeMem para comprobar si pasaba por allí la cosa y así fue... se ejecutaba con normalidad FreeMem. Con eso debería bastar... pero no: el error al salir sigue.
Es justo al momento de salir... en principio el error me debería estar indicando que hay un intento de hacer uso de algún objeto no instanciado o ya liberado pero no hago uso de ningún objeto, variable o lo que fuese ni de los eventos OnClose o OnCloseQuery...
¿Que puede ser?

:'(
Aquí dejo el code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
const
// Tamaño de las matrices
Rows: integer = 92 * 112; //10304
Cols: Integer = 40;
// Precisión del reloj: 1/10000 seg.
// Idea y forma de cálculo basada en:
// [url]http://www.marteens.com/trick4c.htm[/url]
// En teoría es lo más preciso
PrecisionCounter = 10000;
type
// Nuestro tipo para matrices
// 10304 * 40 * 8 = 3297280 bits
// = 3220 Kb
// aprox. 3,1445 Mb
TMatrix = array of array of Double;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Matrix1, Matrix2: TMatrix;
Start, Finish, Freq: Int64;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
i,j: Integer;
begin
// Aquí emplearemos el método "tradicional"
// Activamos "cronómetro"
QueryPerformanceCounter(Start);
//Aqui el algoritmo:
SetLength(Matrix1,Rows,Cols);
// Método seguro. Si bien puede usarse
// for <variable> := 0 to <valor-max> - 1 do
// es conveniente el uso de Low() y High()
for i := Low(Matrix1) to High(Matrix1) do
for j := Low(Matrix1[1]) to High(Matrix1[1]) do
Matrix1[i][j] := i + j;
SetLength(Matrix1,0,0); // O también puede usarse Finalize()
Matrix1 := nil; // preventiva
// Paramos "cronómetro"
QueryPerformanceCounter(Finish);
Label1.Caption := '1/10000 seg: ' +
FormatFloat('0,',(Finish - Start) * PrecisionCounter div Freq);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i,j: Integer;
k: Cardinal;
begin
// Aquí emplearemos el método GetMem/FreeMem
// Activamos "cronómetro"
QueryPerformanceCounter(Start);
//Aqui el algoritmo:
GetMem(Matrix2, SizeOf(Pointer) * Rows + Rows * Cols * SizeOf(Double));
for k := 0 to Rows - 1 do
PPointer(Cardinal(Matrix2) + k*SizeOf(Pointer))^:= Pointer(Cardinal(Matrix2)+SizeOf(Pointer)* Rows + Cols * SizeOf(double)* k);
// Método seguro. Si bien puede usarse
// for <variable> := 0 to <valor-max> - 1 do
// es conveniente el uso de Low() y High()
for i := Low(Matrix2) to High(Matrix2) do
for j := Low(Matrix2[1]) to High(Matrix2[1]) do
Matrix2[i][j] := i + j;
// Según documentación, cuando se trata de arrays dinámicos
// y se utiliza GetMem/FreeMem debe emplearse previamente Finalize
//Finalize(Matrix2); Comentado por un error aquí!
FreeMem(Matrix2, SizeOf(Pointer) * Rows + Rows * Cols * SizeOf(Double));
// Paramos "cronómetro"
QueryPerformanceCounter(Finish);
Label2.Caption := '1/10000 seg: ' +
FormatFloat('0,',(Finish - Start) * PrecisionCounter div Freq);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
// Calculamos la frecuencia a la que corre el reloj
QueryPerformanceFrequency(freq);
end;
end.
Como ven... no hay demasiadas cosas ocultas. Ojalá alguien me pudiera hechar un cable y ver donde está el problema.
Esto me está terminando de convencer que directamente evite todo uso de GetMem, acceso a memoria, los punteros, etc. Les comento los resultados que he obtenido tras 5 pruebas con el método tradicional:
+--------------------+-----+
|Tiempo: 1/10000 seg | CPU |
+--------------------+-----+
| //Antes: | 7% |
+--------------------+-----+
| 461 | 10% |
+--------------------+-----+
| 462 | 10% |
+--------------------+-----+
| 875 | 13% |
+--------------------+-----+
| 471 | 11% |
+--------------------+-----+
| 463 | 16% |
+--------------------+-----+
| Promedio: 546,4 | 12% |
+--------------------+-----+
Considerando que los valores indicados en las constantes son representativos a una de las matrices de mayor dimensión con la que trabajo, y viendo estos números entonces podría llegarse a la conclusión de que SetLength cumple con su propósito de una manera bastante óptima y aceptable.
El uso de la memoria física y virtual no ha variado significativamente, se ha mantenido en los niveles iniciales. Sólo ha llegado a "disparar" los indicadores de CPU y de I/O pero en unos valores se normalizan en un instante. Entre cada prueba se han esperado en promedio minuto y medio.
No ha estado ejecutando ninguna aplicación más salvo la prueba, el Process Explorer de Microsoft y el Antivirus en segundo plano.
Lo que si se ha observado es que una vez finalizada la aplicación y en la espera de una normalización de los indicadores para la prueba con GetMem se ha detectado un disparo de uso de CPU de hasta el 35%. El mismo Explorer indicaba que este empezaba a consumir los recursos. Con cerrarlo y esperar un minuto y medio se volvió a la normalidad.
Las pruebas se realizaron corriendo en una AMD Duron 1.16 GHz, 512 RAM. Si alguien más se anima a someter a prueba las condiciones en sus equipos y compartir sus resultados, le estaría enormemente agradecido.
Saludos,