Альтернативы )))

Любые обсуждения, не нарушающие правил форума.

Модератор: Модераторы

Re: Альтернативы )))

Сообщение скалогрыз » 30.06.2016 06:47:36

Дож писал(а):* Windows 7, i5 2.53Gh 64x, fpc -O3 -Cr 3.0.0rc1 — 4781mls (в 2.5 раз медленнее)
* Raspbian, armv6l 32, fpc -O3 -Cr 2.6.4 — 70436mls (в 7 раз медленнее)

особенности реализации архитектуры? мне кажется среднее как раз в 5 раз медленнее.

Дож писал(а):Но стоп, дженерик же будет практически в точности дублировать то, как работает открытый массив! Вот, например,

мне кажется, в этом примере не хватает кода с инициализаций и передачей параметра непосредственно в функцию.

ну и непосредственно вызов fpc_write_text_sint, занимает с дженериком чуть больше инструкций :)

Дож писал(а):Причём тут дельфи-совместимость, непонятно

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

Дож писал(а):Почему динамический массив должен быть RefCounting? Потому что так его сделали в Delphi? Это не входит в концепцию динамического массива. Почему всё динамическое в языке нужно освобождать ручками, а для динамических массивов сделали особое исключение?

а строки, это не динамическое в язык, о котором заботиться компилятор? а почему дин-массивы не работают как строки (copy-on-write)?

Дож писал(а):(Можно, конечно… через COM-интерфейсы, т.е. через жопу)

а я не согласен, что через жопу. Всего 2 метода добавляется, а QueryInterface можно игнорировать. И вот пожалуйста - полноценная ARC система, можно отрабатывать концепцию сколько влезет.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Альтернативы )))

Сообщение Дож » 30.06.2016 10:10:29

особенности реализации архитектуры? мне кажется среднее как раз в 5 раз медленнее.

Это же беда. Замедление в 7 раз на одной из целевых архитектур — веская причина не использовать -Cr

мне кажется, в этом примере не хватает кода с инициализаций и передачей параметра непосредственно в функцию.

Да пожалуйста:
Код: Выделить всё
{$MODE OBJFPC}
type
generic TOpenArrayOf<T> = object
public type
  P = ^T;
public
  Elements: P;
  Length: LongInt;
  function Get(aElements: P; aLength: LongInt): TOpenArrayOf; static; inline;
end;

TOpenArrayOfLongInt = specialize TOpenArrayOf<LongInt>;

var
  A: array[0..3] of LongInt;
  O: TOpenArrayOfLongInt;

function TOpenArrayOf.Get(aElements: P; aLength: LongInt): TOpenArrayOf;
begin
  Result.Elements := aElements;
  Result.Length := aLength;
end;

{$I-}
procedure PrintLast(const X: array of LongInt); overload;
begin
  Writeln(X[Length(A) - 1]);
end;

procedure PrintLast(X: TOpenArrayOfLongInt); overload;
begin
  Writeln(X.Elements[X.Length - 1]);
end;

begin
  A[3] := 99;
  PrintLast(A);
  PrintLast(TOpenArrayOfLongInt.Get(@A[0], 4));
end.


fpc -al -O3
Код: Выделить всё
# [37] PrintLast(A);
   movl   $U_$P$PROGRAM_$$_A,%eax
   movl   $3,%edx
   call   P$PROGRAM_$$_PRINTLAST$array_of_LONGINT
# [38] PrintLast(TOpenArrayOfLongInt.Get(@A[0], 4));
   movl   $U_$P$PROGRAM_$$_A,%eax
   movl   %eax,(%esp)
   movl   $4,4(%esp)
   movl   %esp,%eax
   call   P$PROGRAM_$$_PRINTLAST$TOPENARRAYOF$1$CRC31B95292

Больше на пару инструкций.

ну и непосредственно вызов fpc_write_text_sint, занимает с дженериком чуть больше инструкций

Не понял: и там, и там есть вызов fpc_write_text_sint, но в функции для открытого массива инструкций суммарно больше. Что такое «непосредственный вызов fpc_write_text_sint»?

а строки, это не динамическое в язык, о котором заботиться компилятор? а почему дин-массивы не работают как строки (copy-on-write)?

Так почему динамический массив должен быть обязательно RefCounted? Почему для него особая честь в сравнении с другими коллекциями? Почему TList не RefCounted, например, это недоработка или как? Действительно, почему динамические массивы не работают как строки? Не должен ли TList тоже работать как строки?

Со строками как таковыми всё понятно — копирование строки является частым явлением, которое хочется оптимизировать, подсчёт ссылок — оправданное решение для них. Какое объяснение про концепцию «динамический массив», зачем ей подсчёт ссылок?

а я не согласен, что через жопу. Всего 2 метода добавляется, а QueryInterface можно игнорировать. И вот пожалуйста - полноценная ARC система, можно отрабатывать концепцию сколько влезет.

Эти два метода неявно впендюриваются ВЕЗДЕ, значительно добавляя время работы.

Вот ещё тест:
Код: Выделить всё
{$MODE OBJFPC}
uses
  SysUtils;

type
IObj1 = interface
  function X: LongInt;
end;

IObj2 = interface
  function I: IObj1;
end;

TObj1 = class{$IFDEF USE_INTERFACE}(TInterfacedObject, IObj1){$ENDIF}
private
  I: LongInt;
public
  constructor Create;
  function X: LongInt;
end;

TObj2 = class{$IFDEF USE_INTERFACE}(TInterfacedObject, IObj2){$ENDIF}
private
  FObj1: {$IFDEF USE_INTERFACE}IObj1{$ELSE}TObj1{$ENDIF};
public
  constructor Create;
  function I: {$IFDEF USE_INTERFACE}IObj1{$ELSE}TObj1{$ENDIF};
end;

constructor TObj1.Create;
begin
  I := 0;
end;

function TObj1.X: LongInt;
begin
  Result := I;
  Inc(I);
end;

constructor TObj2.Create;
begin
  FObj1 := TObj1.Create;
end;

function TObj2.I: {$IFDEF USE_INTERFACE}IObj1{$ELSE}TObj1{$ENDIF};
begin
  Result := FObj1;
end;

var
  Obj2: {$IFDEF USE_INTERFACE}IObj2{$ELSE}TObj2{$ENDIF};
  I: LongInt;
  t : tdatetime;
  k : integer;
  n : integer;

begin
  t:=now;
  Obj2 := TObj2.Create;
  for I := 0 to 1024 * 1024 * 1024 do
    if I > Obj2.I.X then
      Break;
  t:=now-t;
  Writeln(Obj2.I.X);
  writeln('time: ',round( t*MSecsPerDay),'mls');
end.

Запуски:
* Windows 7, i5 2.53Gh 64x, fpc -O3 3.0.0rc1 — 4340mls (время работы примерно соответствует ожиданиям на 2.5ГГц процессоре)
* Windows 7, i5 2.53Gh 64x, fpc -O3 -dUSE_INTERFACE 3.0.0rc1 — 36029mls (интерфейсы замедлили прогу в 9 раз)

С такими подходами (в 5 раз «средние по больнице» потери на Range Check, в 9 раз на COM-интерфейсах и т.д.) и Java окажется очень шустрым языком :)
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Альтернативы )))

Сообщение hinst » 30.06.2016 13:59:31

Ну так не используйте такие подходы которые приводят к замедлению в тех местах где надо чтобы работало быстро
Вы: я использовал тормозящие подходы и теперь я не доволен тем что у меня тормозит
Аватара пользователя
hinst
энтузиаст
 
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Re: Альтернативы )))

Сообщение Дож » 30.06.2016 14:03:39

Вы читали тред или только последнее сообщение? Где я писал, что я использую -Cr или COM-интерфейс? Напротив, я утверждаю, что они отстой, я ими не пользуюсь, и мы со Скалогрызом проводим анализ, чтобы понять плохи ли они в действительности или это мне так кажется.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Альтернативы )))

Сообщение скалогрыз » 30.06.2016 17:13:05

Дож писал(а):Это же беда. Замедление в 7 раз на одной из целевых архитектур — веская причина не использовать -Cr

так я же говорю - для отладки, для отладки использовать!

Дож писал(а):Запуски:
* Windows 7, i5 2.53Gh 64x, fpc -O3 3.0.0rc1 — 4340mls (время работы примерно соответствует ожиданиям на 2.5ГГц процессоре)
* Windows 7, i5 2.53Gh 64x, fpc -O3 -dUSE_INTERFACE 3.0.0rc1 — 36029mls (интерфейсы замедлили прогу в 9 раз)
...
Эти два метода неявно впендюриваются ВЕЗДЕ, значительно добавляя время работы.

Да,я согласен. Работа с объектом через Interface, значительно медленнее работы с объектом на прямую.
Но тут приходится интерфейсы правильно использовать, чтобы свести количество Inc/Dec к минимуму.

Какой-нить DirectX API построен целиком на интерфейсах... и ничего, никто на производительность не жалуется.
Наверное, потому что процент времени обращения к интерфейсам (с его inc/dec ref), на порядки ниже времени непосредственной работы.

Дож писал(а):Не понял: и там, и там есть вызов fpc_write_text_sint, но в функции для открытого массива инструкций суммарно больше. Что такое «непосредственный вызов fpc_write_text_sint»

чтобы получить доступ к указателю и length, приходится делать поправку на "object" - получить адрес object-а, и от него сделать отступ
А при открытых массивах указатель и длинна передаются как параметры :)
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Альтернативы )))

Сообщение Pavia » 30.06.2016 18:56:42

DirectX - как раз и критиковали за его тормознутость. А потом процессоры стали быстрыми, интерфейсы удобнее(производительнее).
100х300х10х1000=100 000 000 или 10% от производительности современного ЦП (3ГГц)
100 кадров в секунду, 300 объектов в кадре 10 вызовов интерфейсов и 1000 тактов на вызов интерфейса.
В играх где надо вывести более 300 объектов используют трюки когда одним вызовом интерфейса обрабатывается 10-100 графических объектов разом.
Пока суммарная производительность интерфейсов менее 10% никто не замечает. А во вторых как-то просто не принята у разработчиков игр жаловаться на DirectX они поэтому и меряют производительность в FPS.
Аватара пользователя
Pavia
постоялец
 
Сообщения: 290
Зарегистрирован: 07.01.2011 12:46:51

Re: Альтернативы )))

Сообщение скалогрыз » 30.06.2016 19:04:45

Pavia писал(а):DirectX - как раз и критиковали за его тормознутость.

Так и OpenGL критиковали за его тормознутость.

Но мне кажется, тут два варианта
* плохой движок (непрямота рук разработчика)
* плохие дрова (непрямота рук разработчика драйвера)
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Альтернативы )))

Сообщение Pavia » 30.06.2016 21:29:25

Так и OpenGL критиковали за его тормознутость.

Поэтому и разработали EGL, что-бы не тормозить. По сути выкинули всё лишнее, все преобразования и др. А МС ничего подобного не сделала. Разве что может похвастаться частичной параллельностью в DX11. Что-бы вызов не тормозил разработчику движка предложили распихать его по разным ядрам.
Аватара пользователя
Pavia
постоялец
 
Сообщения: 290
Зарегистрирован: 07.01.2011 12:46:51

Re: Альтернативы )))

Сообщение AlphaBlend » 30.06.2016 21:33:32

получается , что производители мощных видеокарт наживаются на несостоятельности графических библиотек ? )
Аватара пользователя
AlphaBlend
постоялец
 
Сообщения: 207
Зарегистрирован: 22.05.2016 10:13:10

Re: Альтернативы )))

Сообщение скалогрыз » 30.06.2016 22:32:02

Дож писал(а):Почему динамический массив должен быть RefCounting? Потому что так его сделали в Delphi? Это не входит в концепцию динамического массива. Почему всё динамическое в языке нужно освобождать ручками, а для динамических массивов сделали особое исключение?

Динамических массив это не статических массив, в смысле его поведения (и поведения при в качестве параметра).
Концепция динамического массива, это то, что он в первую очередь Указатель, и только потом Массив.

Пример работы указателей, при передаче их в процедуру в качестве параметра
Код: Выделить всё
procedure DoSomething(data:PInteger);
begin
  ...
  GetMem(data, size2)
  ...
  FreeMem(data);

var
  p : PInteger;
begin
  GetMem(p, size);
  DoSomething(p);  // значение p по выходу из процедуры не изменилось
  FreeMem(p);


С динамическими массивами происходит следующее. При передаче его в процедуру, ни как const или var, у него увеличивается счётчик.
В том случае, если процедура попробует изменить его размер (не содержимое), при условии, что счётчик не нулевой, создасться новый динамический массив, а существующий останется без изменений.
При этом содержимое под указателем, можно безпретятственно менять.

Это так же решает проблему с Realloc-ом. Если выше указанною процедуру переписать, как
Код: Выделить всё
procedure DoSomething(data:PInteger);
begin
  ...
  ReallocMem(data, size2) // перераспределяем память, освободим старый участок и получив новый
  ...

var
  p : PInteger;
begin
  GetMem(p, size);
  DoSomething(p);  // значение p по выходу из процедуры не изменилось
  FreeMem(p);

То при вызове FreeMem, в конце программы, может произойти ошибка. По сути - надёжные типизированные Pointer-ы)


Если статический массив передан в процедуру без указания var или const создаётся его полная копия. (В стеке! ... Привет рекусриям и stackoverflow)

Добавлено спустя 2 минуты 13 секунд:
AlphaBlend писал(а):получается , что производители мощных видеокарт наживаются на несостоятельности графических библиотек ? )

хех. я бы с удовольствием до сих пор бы сидел на XP.
Но злобные софтописатели выпустили новые операционки.
И не менее злобные железкостроители не выпустил драйверов для новых железок под XP.

уж не всемирный ли это заговор!?!?!!? :shock: :o
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Альтернативы )))

Сообщение Дож » 01.07.2016 14:11:29

скалогрыз писал(а):чтобы получить доступ к указателю и length, приходится делать поправку на "object" - получить адрес object-а, и от него сделать отступ
А при открытых массивах указатель и длинна передаются как параметры :)

Это действительно важно? Ты всё ещё считаешь, что «А вот от дженериков функционала открытых массивов ждать не придётся.», даже после приведённых фрагментов кода?

Извини, но мне кажется, что ты в некотором маразме и придумываешь не аргументы к какой-то позиции, а рандомные придирки :) То Slice не нравится, то обёртка слишком толстая, то хочется низкоуровневости, то хочется писать высокоуровенево «array of T» для обхода граблей и т.д., мне надоело пытаться угодить, к тому же я не пользуюсь открытыми массивами и их судьба меня слабо волнует.

Подведём итог, моё мнение: 1) железные люди не играют в азартные игры с компилятором (и пишут (P: Pointer; L: LongInt) или (R: PArrayAsRecord), а не (const A: array of T)), 2) дженерики — превосходный компромисс по удобству+гибкости+производительности в том числе и для открытых массивов, в результате спора и просмотра ассемблерного кода я только больше в этом убедился.

Концепция динамического массива, это то, что он в первую очередь Указатель, и только потом Массив.

Концепция динамического массива — это то, что он массив и то, что его размер определяется в рантайме.
Код: Выделить всё
type
  TDynArrayOfInteger = specialize TDynArrayOf<Integer>;

procedure DoSomething(var data: TDynArrayOfInteger);
begin
  ...
  data.SetLength(size2); // перераспределяем память, освободим старый участок и получив новый
  ...

var
  p : TDynArrayOfInteger;
begin
  p.Init(size);
  DoSomething(p);
  p.Done;

Зачем мне здесь RefCounted и почему программа с ошибочной работой с памятью должна продемонстрировать необходимость RefCounting'а — мне непонятно.

Я с таким же успехом могу сказать: смотрите, утечка памяти!
Код: Выделить всё
procedure f(O: TObject);
begin
  O := TObject.Create;
end;

var
  O: TObject
begin
  O := TObject.Create;
  f(O);
  O.Free; // один объект не будет освобождён!

Ведь TObject — это в первую очередь Указатель, и только потом Объект. С ним можно сделать что-то не так и он утечёт. В паскаль нужно ввести сборщик мусора!
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Альтернативы )))

Сообщение скалогрыз » 01.07.2016 16:31:09

Дож писал(а):Ты всё ещё считаешь, что «А вот от дженериков функционала открытых массивов ждать не придётся.», даже после приведённых фрагментов кода?

Ты же сам при сравнении кодов показывал: 1) сначала нужно объявить переменную деженирка 2) в коде её заполнить данными.
Как минимум это больше писанины. Как маскимум, это лишние инструкции.

Дож писал(а):Зачем мне здесь RefCounted и почему программа с ошибочной работой с памятью должна продемонстрировать необходимость RefCounting'а — мне непонятно.!


Поинтеры:
Код: Выделить всё
{$mode delphi}
uses SysUtils;

var
  p :PInteger;

const
  HitSize = 1024*1024;

procedure Test(d: PInteger);
begin
  writeln('before: ', PtrUInt(d));
  ReallocMem(d, HitSize); 
  writeln('after:  ', PtrUInt(d));
  FreeMem(d); // no leaks!
end;

begin
  try
    GetMem(p, 4);
    writeln('init:   ',PtrUInt(p));
    Test(p);
    writeln('finish: ', PtrUInt(p));
    FreeMem(p);     
  except 
    on e: exception do
      writeln('error: ', e.message);
  end;
end.


Динамические массивы:
Код: Выделить всё
{$mode delphi}
uses SysUtils;

type
  TDynArrayOfInteger =  array of Integer;
var
  p : TDynArrayOfInteger;

const
  HitSize = 1024*1024;

procedure Test(d: TDynArrayOfInteger);
begin
  writeln('before: ', PtrUInt(d));
  SetLength(d, HitSize); 
  writeln('after:  ', PtrUInt(d));
  SetLength(d,0); // no leaks!
end;

begin
  try
    SetLength(p, 1);
    writeln('init:   ',PtrUInt(p));
    Test(p);
    writeln('finish: ', PtrUInt(p));
    SetLength(p,0);     
  except 
    on e: exception do
      writeln('error: ', e.message);
  end;
end.


Добавлено спустя 1 минуту 36 секунд:
Дож писал(а):Я с таким же успехом могу сказать: смотрите, утечка памяти!
...
Ведь TObject — это в первую очередь Указатель, и только потом Объект. С ним можно сделать что-то не так и он утечёт. В паскаль нужно ввести сборщик мусора!

вообще-то, такой код и есть основной довод сторонников добавления сборки мусора :D
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Альтернативы )))

Сообщение Дож » 01.07.2016 17:29:51

скалогрыз писал(а):
Дож писал(а):Ты всё ещё считаешь, что «А вот от дженериков функционала открытых массивов ждать не придётся.», даже после приведённых фрагментов кода?

Ты же сам при сравнении кодов показывал: 1) сначала нужно объявить переменную деженирка 2) в коде её заполнить данными.
Как минимум это больше писанины.

Это выглядит как очередная придирка с уходом в сторону от темы. Либо непонимание.

Открытый массив — это разновидность типа аргумента, передаваемого в функцию. С точки зрения этого аспекта — передачи аргумента в функцию средствами дженерика, я демонстрировал как можно обойтись без нативного открытого массива. Я не писал полный и окончательный код реализации открытого массива.

Фрагмент псеводкода для размышления использования открытого массива на дженериках, в котором 1) не нужно объявлять переменную дженерика 2) не нужно заполнять её данными руками 3) не используются нативные открытые массивы 4) столько же писанины, сколько для array of Integer.
Код: Выделить всё
procedure Foo(const X: TOpenArrayOfInteger);
begin
  Writeln(X[0]);
end;

...

var
  Arr: TDynArrayOfInteger;
begin
  Arr.SetLength(1);
  Arr[0] := 5000;
  Foo(Arr);
end;


Какой из пунктов 1-4 нарушается открытым массивом на дженериках?
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Альтернативы )))

Сообщение скалогрыз » 01.07.2016 17:54:53

Дож писал(а):Фрагмент псеводкода для размышления использования открытого массива на дженериках, в котором 1) не нужно объявлять переменную дженерика 2) не нужно заполнять её данными руками 3) не используются нативные открытые массивы 4) столько же писанины, сколько для array of Integer.
...
Какой из пунктов 1-4 нарушается открытым массивом на дженериках?

а как объявлены TOpenArrayOfInteger и TDynArrayOfInteger?
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Альтернативы )))

Сообщение Дож » 01.07.2016 18:17:04

В идеальном мире они вообще не объявлены, а на их месте просто написано TOpenArrayOf<Integer> и TDynArrayOf<Integer> соответственно
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Пред.След.

Вернуться в Потрепаться

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13

Рейтинг@Mail.ru