О статических и динамических массивах

Скоро будет MaxBy, как в morelinq, тогда эта задача будет довольно просто решаться.

Просто она будет решаться, если будет какой-нибудь .Max2, возвращающий запись вида (индекс,значение). А еще в morelinq есть такая вкусняшка, как Index. Частенько не хватает… Но главное сейчас - это дождаться срезов. Вчера попалась задача порезать массив на три части и в каждой из них реверсировать элементы. На срезах бы решилось крайне элегантно, а так пришлось… ну, сами знаете)).

Да, действительно, когда я поснимал все “птички” в опциях компилятора, получил exe-файлы и запустил их из-под FAR-оболочки, получилось время 703 для статического массива и по 500 для динамических, независимо от использования Swap():

H:\PABCWork.NET>gj0.exe
-1
[[0.999999999999997,-3,2],[-3,3,-1],[2,-1,0]]
703

H:\PABCWork.NET>gj1.exe
-1
[[0.999999999999997,-3,2],[-3,3,-1],[2,-1,0]]
500

H:\PABCWork.NET>gj2.exe
-1
[[0.999999999999997,-3,2],[-3,3,-1],[2,-1,0]]
500

Ниже - тексты программ со статическими и динамическими массивами; вариант без Swap (gj1) приводить не стал.

// PascalABC.NET 3.1, сборка 1171 от 15.02.2016
type
  tMatrix=array[1..3,1..3] of real;
  tRVector=array[1..3] of real;
  tIVector=array[1..3] of integer;

procedure inversion2(n:integer; eps:real; var a:tMatrix; var det:real);
// Обращение матрицы методом Гаусса-Жордана
// Алгоритм 120б. В кн. "Библиотека алгоритмов 101б-150б",
// М.И.Агеев, В.П.Алик, Ю.И.Марков. М.,"Советское радио", 1978
label
  rept,nexti;
var
  y,w:real;
  i,j,k,r,p:integer;
  b,c:trVector;
  z:tIVector;
begin
  det:=1.0;
  for j:=1 to n do z[j]:=j;
  for i:=1 to n do begin
    k:=i; y:=a[i,i];
    r:=i-1; p:=i+1;
    for j:=p to n do begin
      w:=a[i,j];
      if abs(w)>abs(y) then begin k:=j; y:=w end
      end;
    det:=y*det;
    if abs(y)<eps then Exit;
    y:=1/y;
    for j:=1 to n do begin
      c[j]:=a[j,k]; a[j,k]:=a[j,i];
      a[j,i]:=-c[j]*y;
      a[i,j]:=a[i,j]*y; b[j]:=a[i,j]
      end;
    a[i,i]:=y;
    j:=z[i]; z[i]:=k; z[k]:=j;
    for k:=1 to r do begin
      for j:=1 to r do a[k,j]:=a[k,j]-b[j]*c[k];
      for j:=p to n do a[k,j]:=a[k,j]-b[j]*c[k]
      end;
    for k:=p to n do begin
      for j:=1 to r do a[k,j]:=a[k,j]-b[j]*c[k];
      for j:=p to n do a[k,j]:=a[k,j]-b[j]*c[k]
      end;
    end;
  for i:=1 to n do begin
rept:
  k:=z[i];
  if k=i then goto nexti;
  for j:=1 to n do begin
    w:=a[i,j]; a[i,j]:=a[k,j]; a[k,j]:=w
    end;
  p:=z[i]; z[i]:=z[k]; z[k]:=p;
  det:=-det;
  goto rept;
nexti:
  end
end;

begin
  var eps:=0.1e-6;
  var n:=3;
  var dt:real;
  var a:tMatrix;
  for var i:=1 to 1000000 do begin
    a[1,1]:=1; a[1,2]:=2; a[1,3]:=3;
    a[2,1]:=2; a[2,2]:=4; a[2,3]:=5;
    a[3,1]:=3; a[3,2]:=5; a[3,3]:=6;
    inversion2(n,eps,a,dt);
    end;   
  Writeln(dt);
  Writeln(a);
  Writeln(Milliseconds)
end.
// PascalABC.NET 3.1, сборка 1171 от 15.02.2016
procedure inversion2(n:integer; eps:real; var a:array[,] of real; var det:real);
// Обращение матрицы методом Гаусса-Жордана
// Алгоритм 120б. В кн. "Библиотека алгоритмов 101б-150б",
// М.И.Агеев, В.П.Алик, Ю.И.Марков. М.,"Советское радио", 1978
label
  rept,nexti;
var
  y,w:real;
  i,j,k,r,p:integer;
  b,c:array of real;
  z:array of integer;
begin
  SetLength(b,n); SetLength(c,n); SetLength(z,n);
  det:=1.0;
  for j:=0 to n-1 do z[j]:=j;
  for i:=0 to n-1 do begin
    k:=i; y:=a[i,i];
    r:=i-1; p:=i+1;
    for j:=p to n-1 do begin
      w:=a[i,j];
      if abs(w)>abs(y) then begin k:=j; y:=w end
      end;
    det:=y*det;
    if abs(y)<eps then Exit;
    y:=1/y;
    for j:=0 to n-1 do begin
      c[j]:=a[j,k]; a[j,k]:=a[j,i];
      a[j,i]:=-c[j]*y;
      a[i,j]:=a[i,j]*y; b[j]:=a[i,j]
      end;
    a[i,i]:=y;
    j:=z[i]; z[i]:=k; z[k]:=j;
    for k:=0 to r do begin
      for j:=0 to r do a[k,j]:=a[k,j]-b[j]*c[k];
      for j:=p to n-1 do a[k,j]:=a[k,j]-b[j]*c[k]
      end;
    for k:=p to n-1 do begin
      for j:=0 to r do a[k,j]:=a[k,j]-b[j]*c[k];
      for j:=p to n-1 do a[k,j]:=a[k,j]-b[j]*c[k]
      end;
    end;
  for i:=0 to n-1 do begin
rept:
  k:=z[i];
  if k=i then goto nexti;
  for j:=0 to n-1 do Swap(a[i,j],a[k,j]);
  Swap(z[i],z[k]);
  det:=-det;
  goto rept;
nexti:
  end
end;

begin
  var eps:=0.1e-6;
  var n:=3;
  var dt:real;
  var a:array[,] of real;
  SetLength(a,3,3);
  for var i:=1 to 1000000 do begin
    a[0,0]:=1; a[0,1]:=2; a[0,2]:=3;
    a[1,0]:=2; a[1,1]:=4; a[1,2]:=5;
    a[2,0]:=3; a[2,1]:=5; a[2,2]:=6;
    inversion2(n,eps,a,dt);
    end;   
  Writeln(dt);
  Writeln(a);
  Writeln(Milliseconds)
end.

Получается, что в данной реализации компилятора работа с динамическими массивами производительнее. Возможно, причина тут именно в моделировании статических массивов посредством динамических.

Я списывался с ними - они сказали, что у них 3.0 и в следующее обновление будет 3.1, а на сайте написана неправда.

1 лайк

Улыбнуло. Но отрадно, что движение есть. А то дети интересуются, какой смысл изучать новшества, если их применить негде. Каждому не объяснишь, что это новое - на самом деле инвестиции в будущее для тех, кто решил так или иначе заниматься программированием.

Вот в этой статье http://pascalabc.net/stati-po-pascalabc-net/obuchenie-programmirovaniyu/28-meryaem-proizvoditelnost при ее подготовке я в разных вариантах пробовал и статические и динамические массивы. И - то одни работали быстрее, то другие. Я сделал вывод, что сильнее всего тут попадание в кеш процессора.

3 лайка

Вполне вероятно, что Вы правы в своем предположении. Спасибо за ссылку, интересный материал.