Директива компилятора для отключения проверки индексатора массива


#95

Я не про то говорю. Вы сначала сказали что игнорировать опыт что обычно границы массивов надо проверять - нельзя. Но про то что в других .Net языках это можно отключать - вы говорите как будто это рандомное решение а не опыт.

Насчёт ниши - почему вы вдруг говорите что только образование. На паскале полно упрощений, программа на нём получается читабельнее и проще, это тоже обсуждали в той теме.


#96

Вообще муть какая-то. Мне кажется, что этим просто не хотят заниматься.


#97

Вы решили ограничить нишу. Понятно…


#98

Это лишь для совместимости со старым кодом. В Java этого нет.


#99

Почему-то мне думается, что хотелки порулить ссылками - это на самом деле неосознанное желание “поруководить” собственным кодом. Когда компьютеры были большими, а их быстродействие и объемы памяти, наоборот, по современным меркам, ничтожными, операционных систем тоже не было, а все писали непосредственно в машинном коде. Хорошие программисты были на вес золота, потому что они умели втиснуть приличного объема программы в эти смешные несколько сотен ячеек оперативной памяти, да еще и добиться от программы приемлемой скорости вычислений. Вас бы в то время - наигрались бы в кодах всласть. Либо не выжили, как программист. Третьего не было дано. Потом появились операционные системы, пакетная обработка данных - и жить стало еще веселее. Счастливых владельцев ЭВМ заставили сдавать в аренду машинное время, если они не могли сами полезно загрузить машину положенное количество времени. Опять хорошие программисты были на коне. Такой программист с лихвой отрабатывал свою высокую зарплату, создавая эффективные по времени выполнения программы и делая при этом минимальное количество ошибок. Ведь за машинное время надо было платить и один час машинного времени обходился примерно столько же, сколько двухнедельная зарплата программиста. Тогда очень важна была оптимизация алгоритмов, а уж знание тайных особенностей компиляторов, заставляющих их генерировать более быстрый код считалось чуть ли не шаманством.

Но это время прошло и вряд ли вернется в том или ином виде.Сейчас промышленно востребованы языки, порождающие в первую очередь надежный самодокументируемый код. А для задач со 100% загрузкой процессора и редкими прерываниями по вводу-выводу существует своя ниша - суперкомпьютеры, многопроцессорные вычислительные комплексы и т.п. С соответствующими специализированными языками. И это точно не Паскаль.


#100

Всё новое - это хорошо забытое старое :slight_smile:


#101

А вот теперь цифры для Админа(и код тоже):

Uses System;
Uses System.Threading;
Uses System.Threading.Tasks;

type
  PInt32 = ^Int32;

procedure SetVal(arr: array [,] of Int32; val: Int32);
begin
  for Var y := 0 to arr.GetLength(0) - 1 do
    for Var x := 0 to arr.GetLength(1) - 1 do
    begin
      arr[x, y] := val;
    end;
end;

function Look(Arr: array [,] of Int32; Val: Int32): Boolean;
begin
  Result := False;
  for Var y := 0 to arr.GetLength(0) - 1 do
    for Var x := 0 to arr.GetLength(1) - 1 do
    begin
      if(arr[x, y] <> Val)
        Then Result := True;
    end;
end;

begin
  var A := new Int32[1000, 1000];
  var B := new Int32[1000, 1000];
  var C := new Int32[1000, 1000];
  SetVal(A, 2);
  SetVal(B, 3);
  var Aptr := Int32(@A[0, 0]);
  var Bptr := Int32(@B[0, 0]);
  var Cptr := Int32(@C[0, 0]);
  GC.Collect();
  var DT := DateTime.Now;
  for Var n := 0 to 99 do
  begin
    for Var y := 0 to 999 do
    begin
      for Var x := 0 to 999 do
      begin
        PInt32(Pointer(Cptr + (y * 1000 + x) * 4))^ := PInt32(Pointer(Aptr + (y * 1000 + x) * 4))^ * PInt32(Pointer(Bptr + (y * 1000 + x) * 4))^;
      end;
    end;
  end;
  Console.WriteLine('PascalABC.NET. Указатели: ' + (DateTime.Now - DT).TotalMilliseconds.ToString());
  Console.WriteLine('Ошибки: ' + Look(C, 6).ToString());
  DT := DateTime.Now;
  for Var n := 0 to 99 do
  begin
    for Var y := 0 to 999 do
    begin
      for Var x := 0 to 999 do
      begin
        C[x, y] := A[x, y] * B[x, y];
      end;
    end;
  end;
  Console.WriteLine('PascalABC.NET. Индексатор: ' + (DateTime.Now - DT).TotalMilliseconds.ToString());
  Console.ReadLine();
end.

Всё ещё сомневаетесь?

P. S. Все результаты получены в Release.


#102

Время то прошло, да вот необходимость осталась. Качество всегда будет востребовано.


#103

Да, это круто.

for Var x := 0 to 999 do
    begin
      for Var y := 0 to 999 do

Порядок тут надо поменять для чистоты. Но всё равно - в 4 раза. Ну - сделайте соответствующие процедуры - и работайте!

Что касается вытягивания двумерного массива в одномерный - то можно сделать и без извращений:

  var aa := new integer[1000*1000];
  var bb := new integer[1000*1000];
  var cc := new integer[1000*1000];
  loop 100 do
    for Var y := 0 to 999 do
    for Var x := 0 to 999 do
    begin
      var r := y * 1000 + x;
      aa[r] := bb[r]+cc[r];
    end;

Этот код работает еще быстрее вашего

И используйте уже нормальный тип integer и паскалевский вывод хотя бы по writeln

Да и замеры времени по MillisecondsDelta

На всякий случай:


#104

Да, не заметил в спешке. Кстати, преобразование pointer->Int32 занимает время? Её ведь можно сократить. Да и вот ещё что, как видите, после получения адреса вызвал сборщика мусора и массив не сместился. В Паскале всё таки фиксируются массивы?

Да вот привык уже к этому :slight_smile: Очень легко в C# переводить, только := на = менять да и всё :smile:


#105

Напишите-ка лучше скрипт, переводящий C# в PascalABC.NET. Сообщество Вам спасибо скажет


#106

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


#107

Глеб, прочитайте внимательно весь мой пост в параллельной ветке (и статью там же по ссылке – см. ниже) про особенности реализации динамической памяти SOH и LOH в CLR.

Что касается конкретно вашего кода:

  • массив из 10^6 эл-тов всегда будет размещен в LOH;
  • одной команды GC.Collect недостаточно, чтобы инициировать дефрагментацию (compaction) LOH;
  • принудительная однократная дефрагментация LOH может быть инициирована только на .NET 4.5.1 и старше;
  • даже правильно инициированная дефрагментация кучи произойдет асинхронно, т.е. в недетерминированный момент времени, а не сразу после GC.Collect;
  • дефрагментация не обязательно приводит к сдвигу в памяти всех объектов кучи!

#108

Надо попробовать.

Тогда вообще проблем не вижу. У меня нет массивов меньше 80 КБ.


#109

Думаю, всё таки, есть смысл разработать механизм фиксации массива. Например для нейросети, фильтры входного слоя занимают примерно 10 КБ, что заставляет их подчиняться сборщику мусора, хотя обращения к элементам происходится десятки, сотни миллионов раз.


#110

Если на него есть неуправляемый указатель, то он фиксируется.

Не понимаю вашу последнюю фразу. Сборщик мусора собирает то, что уже не нужно. Вы хотите это оставить в памяти?


#111

Нет, это был ответ на это:


#112

Если что-то плохо лежит - пусть себе лежит дальше. Мы будем брать то, что лежит хорошо! :sunglasses:

(не помню источник)


#113

А чего ж Вы сразу то не сказали? Вы ведь говорили, что его можно переместить сборщиком мусора и тогда указатель не будет указывать на массив?