![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Преобразование Byte в Word?
ZV © (2011-01-26 17:04:00)Как в Delphi преобразовать 2 значения Byte в Word. На Си делаю побитовый сдвиг и наложение маски а как это сделать в Delphi? Может есть какая функция или делать так же как и на Си. Может кто покажет пример?
Anatoly Podgoretsky (2011-01-31 11:22:00) [1]> sniknik (31.01.2011 09:28:36) [36]
Правильно, главный, их код нам и нафиг не нужен.
sniknik (2011-01-31 09:28:00) [2]> uniken1 © (31.01.11 08:04) [34]
если бы не динамический массив... не все так страшно, хотя предпочел бы типа (соглашения о передаче параметров из функции вроде неизменны) -
function TwoByteToWord(AByte1, AByte2: Byte): Word;
asm
mov al, AByte1
mov ah, AByte2
end;
> почему с нами не поделились
главный вопрос...
Anatoly Podgoretsky (2011-01-31 08:48:00) [3]> uniken1 (31.01.2011 08:04:34) [34]
Лучше подумать, что курили разработчки и почему с нами не поделились
uniken1 (2011-01-31 08:04:00) [4]
> и еще на конкурс извращенцев...
Интересно на какое место попадет функция
TwoByteToWord из Indy модуль(IdGlobal)? Собственный динамический массив с изменением размера и с двойным преобразованием.
Появляются подозрения, что Indy не очень-то оптимальна по производительности.
RWolf (2011-01-28 10:28:00) [5]или смысл в том, чтобы загнать тест в свопы?
RWolf (2011-01-28 10:20:00) [6]
C:\>hilo_word.exe 67108864
Random: 0. 2187500 x 100ns
Combine: 0. 10781250 x 100ns
Combine: 0. 10625000 x 100ns
Combine: 0. 10468750 x 100ns
Cast: 0. 19218750 x 100ns
Combine: 0. 10468750 x 100ns
Map: 0. 18593750 x 100ns
Combine: 0. 10468750 x 100ns
Cast: 0. 20156250 x 100ns
Map: 0. 18593750 x 100ns
Map: 0. 18437500 x 100ns
Cast: 0. 19687500 x 100ns
Атлон64 3000+. Налицо двукратный выигрыш shl-or.
И почему вдруг в Дельфи опасно пользоваться приведением типа, и чем Дельфи в этом смысле отличается от Си?
han_malign (2011-01-28 09:45:00) [7]И о главном: почему опасно пользоваться приведением типа для доступа к битовым полям(в Delphi, в C - все порадужней), и когда таблица таки выгодна...
(посвящается структуре TRGBQuad)
program hilo_word;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
Windows, SysUtils;
const repeatCount = 10;
type
TLoHiWord = packed record
case Integer of
0 : (Lo, Hi : Byte);
1 : (value : Word);
end;
PLoHiWord = ^TLoHiWord;
PByteArray = ^TByteArray;
TByteArray = array[word]of byte;
PWordArray = ^TWordArray;
TWordArray = array[word]of word;
var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);
end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
WriteLn(title:10,': ', _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, '.', _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, ' x 100ns' );
end;
function TRANSFORM(val: word): word;
begin
//ну пускай будет BGR16 в BGR15
Result:= val and $1F or (val shr 1) and $7FE;
end;
const _title: array[0..2]of string = ('Combine', 'Cast', 'Map');
var rgwLookup: array[byte,byte]of word;
var
pbl, pbh: PByteArray;
pw: PWordArray;
alloc, base, i, cnt: cardinal;
si: TSystemInfo;
_b2w: TLoHiWord;
choice: integer;
_hitChoice: array[0..2]of integer;
fdwDoneChoice: LongWord;
begin
alloc:= 0;
if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
if( alloc = 0 )then alloc:= 1024*1024*1024;
GetSystemInfo(si);
inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);
pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
if( pbl = nil )then begin
Writeln('Alloc failed - ', GetLastError());
end;
//prepare lookup table
for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i]:= TRANSFORM(i);
base:= alloc div 4;
Write('GO'#13);
_startProfile;
for i:= 0 to base*2 - 1 do PWordArray(pbl)[i]:= Random(65536);
_stopProfile('Random');
pbh:= PByteArray(@pbl[base]);
pw:= PWordArray(@pbh[base]);
FillChar(_hitChoice, sizeof(_hitChoice), 0);
fdwDoneChoice:= 0;
while( fdwDoneChoice <> 7 )do begin
//дабы никому не пришло в голову упрекнуть меня в предвзятости
choice:= Random(3);
inc(_hitChoice[choice]);
if( _hitChoice[choice] > 2 )then fdwDoneChoice:= fdwDoneChoice or (1 shl choice);
_startProfile;
for cnt:= 1 to repeatCount do begin
case(choice)of
0: for i:= 0 to base - 1 do pw[i]:= TRANSFORM((pbh[i] shl 8) or pbl[i]);
1: for i:= 0 to base - 1 do with _b2w do begin
lo:= pbl[i];
hi:= pbh[i];
pw[i]:= TRANSFORM(value);
end;
2: for i:= 0 to base - 1 do pw[i]:= rgwLookup[pbl[i], pbh[i]];
end;
Write(cnt:2,#13);
end;
_stopProfile(_title[choice]);
end;
VirtualFree(pbl, 0, MEM_RELEASE);
end.
--------------------------------------
Cast: 0. 274687500 x 100ns
Map: 0. 90000000 x 100ns
Combine: 0. 141250000 x 100ns
Combine: 0. 141250000 x 100ns
Cast: 0. 275000000 x 100ns
Cast: 0. 275000000 x 100ns
Map: 0. 89843750 x 100ns
Combine: 0. 141250000 x 100ns
Map: 0. 90000000 x 100ns
12 (2011-01-28 09:44:00) [8]
> han_malign (27.01.11 17:40) [22]
> Игорь Шевченко © (27.01.11 18:13) [24]
вы - маньяки :)
han_malign (2011-01-28 09:02:00) [9]
> отсюда возникает вопрос - что тестируем ?
- вы ничего не тестируете, поскольку подбираете условия по каким то выгодным вам критериям...
Между прочим, если совсем исключить из теста Combine инициализацию страниц памяти нулем при первом обращении(заполнив Random-ом всю выделенную память, а не первую половину) - отрыв еще больше увеличивается...
З.Ы. Самое прикольное это - rgwLookup[Hi, Lo] - как по вашему вычисляется смещение, если адресная арифметика поддерживает только масштабы 1, 2, 4, 8...
Inovet (2011-01-27 19:54:00) [10]> [18] han_malign (27.01.11 08:41)
> [19] RWolf © (27.01.11 09:25)
> Самый быстрый — это сдвиг + OR.
Это в произвольном случае, а когда надо всё время и так и так обращаться, то лучше ничего не делать а сразу организовать хранение рядом, я об этом говорил. Хотя как оно там будет на каком железе должно
> [20] Игорь Шевченко © (27.01.11 10:30)
> подкрепляются тестовыми измерениями
Игорь Шевченко (2011-01-27 18:39:00) [11]
> и естественно - все Page Fault достались Combine...
отсюда возникает вопрос - что тестируем ?
han_malign (2011-01-27 18:33:00) [12]и естественно - все Page Faultдостались Combine...
han_malign (2011-01-27 18:27:00) [13]
> Lookup: 0. 15156250 x 100ns
> Random: 0. 25625000 x 100ns
- молодец, но даже учитывая, что тест всегда обращается к rgwLookup[ 0, 0], поскольку память инициализирована нулями - таблица все равно самый плохой вариант...
Игорь Шевченко (2011-01-27 18:13:00) [14]
program BtoWProfile;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
Windows,
SysUtils;
const repeatCount = 10;
type
TLoHiWord = packed record
case Integer of
0 : (Lo, Hi : Byte);
1 : (value : Word);
end;
PByteArray = ^TByteArray;
TByteArray = array[word]of byte;
PWordArray = ^TWordArray;
TWordArray = array[word]of TLoHiWord;
var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);
end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
WriteLn(title:10,': ', _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, '.', _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, ' x 100ns' );
end;
var rgwLookup: array[byte,byte]of word;
var
pbl, pbh: PByteArray;
pw: PWordArray;
alloc, base, i, cnt: cardinal;
si: TSystemInfo;
begin
alloc:= 0;
if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
if( alloc = 0 )then alloc:= 256*1024*1024;
GetSystemInfo(si);
inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);
pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
if( pbl = nil )then begin
Writeln('Alloc failed - ', GetLastError());
end;
//prepare lookup table
for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i].value:= i;
base:= alloc div 4;
Write('GO'#13);
pbh:= PByteArray(@pbl[base]);
pw:= PWordArray(@pbh[base]);
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do pw[i].value:= (pbh[i] shl 8) or pbl[i];
Write(cnt:2,#13);
end;
_stopProfile('Combine');
_startProfile;
for cnt:= 1 to repeatCount do begin
move(pbl^, pw^, base*2);
Write(cnt:2,#13);
end;
_stopProfile('just copy');
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do pw[i].value:= rgwLookup[pbl[i], pbh[i]];
Write(cnt:2,#13);
end;
_stopProfile('Lookup');
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do PWordArray(pbl)[i].value:= Random(65536);
Write(cnt:2,#13);
end;
_stopProfile('Random');
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do with pw[i] do begin
lo:= pbl[i];
hi:= pbh[i];
end;
Write(cnt:2,#13);
end;
_stopProfile('Direct');
VirtualFree(pbl, 0, MEM_RELEASE);
end.
Игорь Шевченко (2011-01-27 18:12:00) [15]Я несколько изменил порядок тестов
Combine: 0. 13437500 x 100ns
just copy: 0. 7031250 x 100ns
Lookup: 0. 15156250 x 100ns
Random: 0. 25625000 x 100ns
Direct: 0. 13281250 x 100ns
han_malign (2011-01-27 17:40:00) [16]
> ты спутал, батя
- я изредка брежу, но редко путаю:program hilo_word;
{$APPTYPE CONSOLE}
{$IF CompilerVersion >= 15.0}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_CAST OFF}
{$IFEND}
uses
Windows, SysUtils;
const repeatCount = 10;
type
TLoHiWord = packed record
case Integer of
0 : (Lo, Hi : Byte);
1 : (value : Word);
end;
PByteArray = ^TByteArray;
TByteArray = array[word]of byte;
PWordArray = ^TWordArray;
TWordArray = array[word]of TLoHiWord;
var _ft_start: TFileTime;
procedure _startProfile;
var _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_start);
end;
procedure _stopProfile(const title: string);
var _ft_end, _ftDumb: TFileTime;
begin
GetThreadTimes(GetCurrentThread(), _ftDumb, _ftDumb, _ftDumb, _ft_end);
WriteLn(title:10,': ', _ft_end.dwHighDateTime - _ft_start.dwHighDateTime, '.', _ft_end.dwLowDateTime - _ft_start.dwLowDateTime:10, ' x 100ns' );
end;
var rgwLookup: array[byte,byte]of word;
var
pbl, pbh: PByteArray;
pw: PWordArray;
alloc, base, i, cnt: cardinal;
si: TSystemInfo;
begin
alloc:= 0;
if( ParamCount > 0 )then alloc:= StrToIntDef(ParamStr(1), 0);
if( alloc = 0 )then alloc:= 1024*1024*1024;
GetSystemInfo(si);
inc(alloc, cardinal(-alloc) mod si.dwAllocationGranularity);
pbl:= PByteArray(VirtualAlloc(nil, alloc, MEM_COMMIT, PAGE_READWRITE));
if( pbl = nil )then begin
Writeln('Alloc failed - ', GetLastError());
end;
//prepare lookup table
for i:= 0 to $FFFF do PWordArray(@rgwLookup)[i].value:= i;
base:= alloc div 4;
Write('GO'#13);
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do PWordArray(pbl)[i].value:= Random(65536);
Write(cnt:2,#13);
end;
_stopProfile('Random');
pbh:= PByteArray(@pbl[base]);
pw:= PWordArray(@pbh[base]);
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do pw[i].value:= (pbh[i] shl 8) or pbl[i];
Write(cnt:2,#13);
end;
_stopProfile('Combine');
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do with pw[i] do begin
lo:= pbl[i];
hi:= pbh[i];
end;
Write(cnt:2,#13);
end;
_stopProfile('Direct');
_startProfile;
for cnt:= 1 to repeatCount do begin
for i:= 0 to base - 1 do pw[i].value:= rgwLookup[pbl[i], pbh[i]];
Write(cnt:2,#13);
end;
_stopProfile('Lookup');
_startProfile;
for cnt:= 1 to repeatCount do begin
move(pbl^, pw^, base*2);
Write(cnt:2,#13);
end;
_stopProfile('just copy');
VirtualFree(pbl, 0, MEM_RELEASE);
end.
-----------------------------------------------------
Random: 0. 106406250 x 100ns
Combine: 0. 52500000 x 100ns
Direct: 0. 55781250 x 100ns
Lookup: 0. 91406250 x 100ns
just copy: 0. 33125000 x 100ns
Германн (2011-01-27 15:10:00) [17]
> han_malign (27.01.11 08:41) [18]
>
>
> > А какой будет самым быстрым? Случайно не [10]?
>
> - случайно:
> Германн © (26.01.11 17:21) [2]
> 1. Word1:=Byte1+(Byte2 shl 8)
>
> - т.к. нет лишних обращений к памяти, а таких регистровых
> операций - современные CPU хавают по десятку за такт...
>
Хорошо подумал прежде чем написать такую чушь?
Нахрена нужны какие-то "операции" для того, чтобы всего лишь расположить два байта рядом в памяти???
Игорь Шевченко (2011-01-27 10:30:00) [18]
> - т.к. нет лишних обращений к памяти, а таких регистровых
> операций - современные CPU хавают по десятку за такт...
обычно подобные утверждения подкрепляются тестовыми измерениями.
> Недаром девиз Мелкомягких - "Все что можно пересчитать -
> лучше не хранить"...
кто не работает - не ест, ты спутал, батя
RWolf (2011-01-27 09:25:00) [19]
> Inovet © (27.01.11 05:45) [15]
> > [12] Студент (27.01.11 04:42)> А какой будет самым быстрым?
> Самый быстрый, который ничего не делает - с рекордом и с
> массивом,
Самый быстрый — это сдвиг + OR.
han_malign (2011-01-27 08:41:00) [20]
> А какой будет самым быстрым? Случайно не [10]?
- случайно:
Германн © (26.01.11 17:21) [2]
1. Word1:=Byte1+(Byte2 shl 8)
- т.к. нет лишних обращений к памяти, а таких регистровых операций - современные CPU хавают по десятку за такт...
Недаром девиз Мелкомягких - "Все что можно пересчитать - лучше не хранить"...