sizeOf - jak to działa?

0

Siema, czy ktoś może mi wyjaśnić jak działa sizeOf? Tzn. wg mnie zachowanie jest dziwne.

Mam rekord:

type
  THeader = packed record
    FileType: string[4];
    CryptKey: integer;
    QStart: int64;
    CCount: integer;
    QCount: integer;
  end;

sizeof(THeader) zwraca mi 25. Dlaczego 25? Skąd ten dodatkowy bajt?
Bez słówka "packed" zwraca 32.

A może pytanie powinno brzmieć inaczej: dlaczego ten rekord ma 25 bajtów, a nie 24.
Również nie rozumiem, dlaczego bez packed ma 32.

0

sizeof(THeader) zwraca mi 25. Dlaczego 25? Skąd ten dodatkowy bajt?

U mnie zwraca 24, a z "packed" 19.

Również nie rozumiem, dlaczego bez packed ma 32.

Niedawno był tutaj podobny temat, tylko ktoś pytał się o umieszczenie zmiennych w pamięci w C++.
Powód jest prosty: odczytanie 32 bajtów z pamięci jest szybsze, niżeli odczytanie 25 bajtów.
Dlaczego?
Otóż procesor ma 32 lub 64 bitowe rejestry, tak więc odczytanie paczki, które jest wyrównana do rozmiaru rejestru, jest szybsze, niżeli odczytanie paczki, która nie jest wyrównana.
Stąd kompilator wyrównuje rozmiary rekordu (tak samo jak klas czy umieszczenia samych zmiennych w pamięci) do potęgi czwórki.
Link do tematu: Rozmieszczenie zmiennych w pamięci
Tam to opisali lepiej, niż ja ;)

1

Stąd kompilator wyrównuje rozmiary rekordu (tak samo jak klas czy umieszczenia samych zmiennych w pamięci) do potęgi czwórki.

Aj nie prawda, kompilatory wyrównują według Intel ABI bo Intel tak zaleca.

Powód jest prosty: odczytanie 32 bajtów z pamięci jest szybsze, niżeli odczytanie 25 bajtów.
Dlaczego?
Otóż procesor ma 32 lub 64 bitowe rejestry, tak więc odczytanie paczki, które jest wyrównana do rozmiaru rejestru, jest szybsze, niżeli odczytanie paczki, która nie jest wyrównana.

Dlaczego czytając więcej bajtów jest szybciej? Bo jest wyalignowane! Co ma jedno do drugiego to mniejsza.
Koledze się coś pomieszało:
#Rozmiar nie ma nic do alignowania.
#Przeczytanie 25 bajtów jest szybsze lub tak samo szybkie jak 32 bajtów zakładając że są tak samo wyrównane.
#Nie alignuje się do 32 bajtów, 16 to bodaj najwięcej ile widziałem (dla procedur w FPC jest takie alignowanie).

sizeof(THeader) zwraca mi 25. Dlaczego 25? Skąd ten dodatkowy bajt?

Bo shortstring ma ZAWSZE dodatkowy bajt który definiuje długość?

Również nie rozumiem, dlaczego bez packed ma 32.

Wyrównanie.

U mnie zwraca 24, a z "packed" 19.

Ciekawe jak 19 skoro z samych pól liczbowych wychodzi 20 bajtów.

0

Ciekawe jak 19 skoro z samych pól liczbowych wychodzi 20 bajtów.

http://ideone.com/KNAlY także nie mam pojęcia jak.
Na Windowsie 32 oraz 25 bajtów.

0
Patryk27 napisał(a):

Ciekawe jak 19 skoro z samych pól liczbowych wychodzi 20 bajtów.

http://ideone.com/KNAlY
Na Windowsie 32 oraz 25 bajtów.

To zobacz ile ma tam integer... Ciekawe.

Zresztą, wersja jest archaiczna więc nie sugerowałbym się (fpc 2.2.0).

0
-123oho napisał(a):

#Rozmiar nie ma nic do alignowania.

Alignuje się do wielokrotności rozmiaru danego typu danych z poprawką na potęgi dwójki, co ma przełożenie na rozmieszczenie w liniach cache'u - gwarantuje umieszczenie pojedynczego elementu w najmniejszej możliwej ilości linii cache'u (czyli jednej, obecnie nie ma typów danych wykraczających poza 32 bajty).

-123oho napisał(a):

#Przeczytanie 25 bajtów jest szybsze lub tak samo szybkie jak 32 bajtów zakładając że są tak samo wyrównane.
#Nie alignuje się do 32 bajtów, 16 to bodaj najwięcej ile widziałem (dla procedur w FPC jest takie alignowanie).

Kod wyrównuje się do 16 bajtów ze względu na to, że maksymalny rozmiar pojedynczej instrukcji to 15 bajtów...

0

Alignuje się do wielokrotności rozmiaru danego typu danych z poprawką na potęgi dwójki, co ma przełożenie na rozmieszczenie w liniach cache'u - gwarantuje umieszczenie pojedynczego elementu w najmniejszej możliwej ilości linii cache'u (czyli jednej, obecnie nie ma typów danych wykraczających poza 32 bajty).

Chodziło mi o to że mogę dowolnie mieszać alignowanie i rozmiar, wiem że w Intel ABI alignowanie zależy od rozmiaru.

Kod wyrównuje się do 16 bajtów ze względu na to, że maksymalny rozmiar pojedynczej instrukcji to 15 bajtów...

Czyli każda procedura ma jedną instrukcję? Nie widzę związku... Instrukcje nie są alignowane, natomiast każda procedura (do której jest call) jest alignowana.

0

Tak samo alignuje się adresy skoków, nie tylko funkcje: bierze się pod uwagę to, że jak najwięcej instrukcji po skoku powinno się mieścić w linii cache'u, linia to 32 bajty, maksymalna wielkość instrukcji to 15 bajtów, więc 16 bajtów to efektywne minimum, czego nie rozumiesz?

0
PS napisał(a):

Tak samo alignuje się adresy skoków, nie tylko funkcje: bierze się pod uwagę to, że jak najwięcej instrukcji po skoku powinno się mieścić w linii cache'u, linia to 32 bajty, maksymalna wielkość instrukcji to 15 bajtów, więc 16 bajtów to efektywne minimum, czego nie rozumiesz?

A ile jest instrukcji 15 bajtowych? Nie widzę uzasadnienia alignowania do 16 bajtów tym że instrukcje mają do 15 bajtów, zwłaszcza że 15 bajtowe instrukcje nie występują w normalnym kodzie. Najczęściej występują instrukcje do 6-7 bajtów.
A to że alignuje się po to żeby do cache łatwo wchodziło to wiem.

0

Nie musisz widzieć uzasadnienia, dekodery obsługują ciągi do 15 bajtów, sugestia pochodzi od samego Intela. Poza tym przy wyrównaniu do 16 bajtów masz 50% szansy na trafienie w początek linii cache'u, nie w środek, co może dać lekki przyrost wydajności i jednocześnie nie marnuje za wiele przestrzeni (specjalne formy nopów mogą mieć dowolny rozmiar, do 15 bajtów), wykonują się jeden cykl lub wręcz na poziomie dekoderów, zależnie od układu i producenta.

0

Nie musisz widzieć uzasadnienia, dekodery obsługują ciągi do 15 bajtów, sugestia pochodzi od samego Intela.

Intel wiele nielogicznych rzeczy pisze w swoich dokumentach, często też niepotwierdzonych w praktyce, więc logikę "bo to powiedział intel" zachowaj dla siebie.

Poza tym przy wyrównaniu do 16 bajtów masz 50% szansy na trafienie w początek linii cache'u, nie w środek, co może dać lekki przyrost wydajności i jednocześnie nie marnuje za wiele przestrzeni

No przecież po to się alignuje.

specjalne formy nopów mogą mieć dowolny rozmiar, do 15 bajtów

A może łatwiej jednak zastosować krótki skok bezwarunkowy? I kto stosuje takie nopy? Głupoty kolego pierniczysz bo kompilatory nigdy nie wyrównują "specjalnymi nopami" każdej instrukcji do 16 bajtów.

wykonują się jeden cykl lub wręcz na poziomie dekoderów, zależnie od układu i producenta.

A mi się wydaje że jednak zwykłe nopy byłyby szybsze po procesor jest do nich bardziej przyzwyczajony już o krótkich jumpach w obrębie tej samej/następnej linii cache nie mówiąc.

Krótko mówiąc: To że instrukcja ma do 15 bajtów nijak ma się do jej alignowania (zwłaszcza że jest bardzo mało instrukcji 15 bajtowych, a gdyby nie ograniczenie to dałoby się dać więcej np. 16 bajtów z sensowną instrukcją [o jak ładnie wyrównane]. To jest po prostu ograniczenie wczesnych procesorów zachowane do dziś). Natomiast jeżeli chodzi o względy szybkości cache/pamięci to jak najbardziej.

0
-123oho napisał(a):

Intel wiele nielogicznych rzeczy pisze w swoich dokumentach, często też niepotwierdzonych w praktyce, więc logikę "bo to powiedział intel" zachowaj dla siebie.

Tylko jeśli czytasz manuale na wyrywki.

-123oho napisał(a):

A może łatwiej jednak zastosować krótki skok bezwarunkowy? I kto stosuje takie nopy? Głupoty kolego pierniczysz bo kompilatory nigdy nie wyrównują "specjalnymi nopami" każdej instrukcji do 16 bajtów.

Wyrównywanie ma sens jedynie przy wielokrotnie wykonywanych skokach, np. początki iteracji pętli, procesor musi mieć czym "nakarmić" dekodery jak najmniejszym kosztem. Zastosowanie skoków bezwarunkowych nie ma najmniejszego sensu, wymaga przynajmniej częściowego opróżnienia potoków, co cholernie nieciekawie wpływa na wydajność, wprowadza opóźnienia, których nie wnoszą nopy.

-123oho napisał(a):

A mi się wydaje że jednak zwykłe nopy byłyby szybsze po procesor jest do nich bardziej przyzwyczajony już o krótkich jumpach w obrębie tej samej/następnej linii cache nie mówiąc.

Misiom zamelduj, szersze formy nopów powstały właśnie po to żeby unikać wyrównywania normalnymi (wolniejszymi) instrukcjami, czy wręcz katastrofalnie wolnymi skokami.

-123oho napisał(a):

Krótko mówiąc: To że instrukcja ma do 15 bajtów nijak ma się do jej alignowania (zwłaszcza że jest bardzo mało instrukcji 15 bajtowych, a gdyby nie ograniczenie to dałoby się dać więcej np. 16 bajtów z sensowną instrukcją [o jak ładnie wyrównane]. To jest po prostu ograniczenie wczesnych procesorów zachowane do dziś).

Doskonale widać, że nie masz zielonego pojęcia o temacie, nie legalnych instrukcji mających 15 bajtów, wszystkie są krótsze. Dekodery obsługują mimo wszystko nadmiarowe prefiksy, łącznie do 15 bajtów instrukcji, jak najbardziej ma to przełożenie na cache i wyrównanie, procesor po skoku powinien móc przynajmniej częściowo zapełnić potoki bez dodatkowego przestoju, skoro dekoder łapie do 15 bajtów to do ilu musisz wyrównać lokalizację skoku żeby zminimalizować ilość fetchowania do cache'u?

0
Patryk27 napisał(a)

Faktycznie, nieco z tego powodu zgłupiałem :P sizeof(Integer) na Ideone jest równe 2, a nie 4.

sizeof(integer) zależy od kompilatora. W Turbo Pascalu to było 2. W Delphi to jest 4.
We FreePascalu zależy od ustawień. Domyślnie jest 2. Ale jeśli się dopisze {$MODE OBJFPC} albo {$MODE DELPHI}, to będzie 4.

0
PS napisał(a):
-123oho napisał(a):

Intel wiele nielogicznych rzeczy pisze w swoich dokumentach, często też niepotwierdzonych w praktyce, więc logikę "bo to powiedział intel" zachowaj dla siebie.

Tylko jeśli czytasz manuale na wyrywki.

-123oho napisał(a):

A może łatwiej jednak zastosować krótki skok bezwarunkowy? I kto stosuje takie nopy? Głupoty kolego pierniczysz bo kompilatory nigdy nie wyrównują "specjalnymi nopami" każdej instrukcji do 16 bajtów.

Wyrównywanie ma sens jedynie przy wielokrotnie wykonywanych skokach, np. początki iteracji pętli, procesor musi mieć czym "nakarmić" dekodery jak najmniejszym kosztem. Zastosowanie skoków bezwarunkowych nie ma najmniejszego sensu, wymaga przynajmniej częściowego opróżnienia potoków, co cholernie nieciekawie wpływa na wydajność, wprowadza opóźnienia, których nie wnoszą nopy.

-123oho napisał(a):

A mi się wydaje że jednak zwykłe nopy byłyby szybsze po procesor jest do nich bardziej przyzwyczajony już o krótkich jumpach w obrębie tej samej/następnej linii cache nie mówiąc.

Misiom zamelduj, szersze formy nopów powstały właśnie po to żeby unikać wyrównywania normalnymi (wolniejszymi) instrukcjami, czy wręcz katastrofalnie wolnymi skokami.

-123oho napisał(a):

Krótko mówiąc: To że instrukcja ma do 15 bajtów nijak ma się do jej alignowania (zwłaszcza że jest bardzo mało instrukcji 15 bajtowych, a gdyby nie ograniczenie to dałoby się dać więcej np. 16 bajtów z sensowną instrukcją [o jak ładnie wyrównane]. To jest po prostu ograniczenie wczesnych procesorów zachowane do dziś).

Doskonale widać, że nie masz zielonego pojęcia o temacie, nie legalnych instrukcji mających 15 bajtów, wszystkie są krótsze. Dekodery obsługują mimo wszystko nadmiarowe prefiksy, łącznie do 15 bajtów instrukcji, jak najbardziej ma to przełożenie na cache i wyrównanie, procesor po skoku powinien móc przynajmniej częściowo zapełnić potoki bez dodatkowego przestoju, skoro dekoder łapie do 15 bajtów to do ilu musisz wyrównać lokalizację skoku żeby zminimalizować ilość fetchowania do cache'u?

Przestań na mnie patrzeć z góry to porozmawiamy. Nie mam po co rozmawiać z osobą która twierdzi że nic nie wiem. Pozdrawiam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1