Dlaczego używać Int 64 na pętli for?
łatwo odpowiedzieć:
- Nie ma potrzeby, aby zrobić wiele iteracji potrzebować Int64, zrób pętlę od 5E9 do 5E9 + 2 (w sumie trzy iteracji).
- To jest tak, że wartości na iteracji są większe niż to, co Int32 może pomieścić
przykład:
procedure Why_Int64_Would_Be_Great_On_For_Loop;
const
StartValue=5000000000; // Start form 5E9, 5 thousand millons
Quantity=10; // Do it ten times
var
Index:Int64;
begin
for Index:=StartValue to StartValue+Quantity-1
do begin // Bla bla bla
// Do something really fast (only ten times)
end;
end;
Ten kod weźmie w ogóle czasu, to jest tak, że wartość indeksu potrzebie być daleko niż 32-bitowy limit całkowity.
Rozwiązaniem jest to zrobić za pomocą pętli while:
procedure Equivalent_For_Loop_With_Int64_Index;
const
StartValue=5000000000; // Start form 5E9, 5 thousand millons
Quantity=10; // Do it ten times
var
Index:Int64;
begin
Index:=StartValue;
while Index<=StartValue+Quantity
do begin // Bla bla bla
// Do something really fast (only ten times)
Inc(Index);
end;
end;
Więc dlaczego kompilator odmawia skompilować pętlę Foor widzę żadnego powodu ... każdy pętli mogą być automatycznie tłumaczone na język pętla while ... i prekompilator może to zrobić przed kompilatorem (tak jak inne optymalizacje) ... jedyny powód, dla którego widzę, to leniwi ludzie, którzy tworzą kompilator, który nie myślał o tym.
Jeśli dla jest zoptymalizowany, więc może korzystać tylko z indeksu 32-bitowego, to jeśli kod próbuje użyć indeksu 64-bitowego, nie może być zoptymalizowany, więc czemu nie pozwolić, by optymalizator pre-kompilatora wyszukał to dla nas ... tylko daje zły obraz programistom !!!
Nie chcę, aby ktokolwiek ungry ...
Ja tylko po prostu powiedzieć coś oczywistego ...
Nawiasem mówiąc, nie wszyscy ludzie zaczynają pętlę Foor na zero (lub jeden) wartości ... czasami trzeba zacząć od naprawdę dużych wartości.
Jest zawsze dobrze powiedział, że jeśli trzeba coś zrobić określoną liczbę razy ty najlepszego wykorzystania dla pętli zamiast pętli while ...
też mogę coś powiedzieć ... takich dwóch wersjach pętla for i while, która używa Inc (Index) są równie szybkie ... ale jeśli umieścisz krok pętli while jako Index: = Index + 1; jest wolniej; to naprawdę nie jest wolniejsze, ponieważ pre-kompilator optimizator zobaczyć, że i używać Inc (Indeks) zamiast ... można sprawdzić, czy kupić robi następny:
// I will start the loop from zero, not from two, but i first do some maths to avoid pre-compiler optimizator to convert Index:=Index+Step; to Inc(Index,Step); or better optimization convert it to Inc(Index);
Index:=2;
Step:=Index-1; // Do not put Step:=1; or optimizator will do the convertion to Inc()
Index:=Step-2; // Now fix, the start, so loop will start from zero
while Index<1000000 // 1E6, one millon iterations, from 0 to 999999
do begin
// Do something
Index:=Index+Step; // Optimizator will not change this into Inc(Index), since sees that Step has changed it's value before
end;
optymalizator widać zmienna nie zmieniają swoją wartość, więc może go przekonwertować na stałą, a następnie na przypisanie przyrostu, jeśli dodasz stałą (zmienna: = stała + zmienna), to zoptymalizuje ją do wartości Inc (zmienna, stała) iw przypadku, gdy zobaczy taką stałą 1, będzie również optims it to Inc (variable) ... i takie optymizacje w niskim poziomie języka komputerowego są bardzo zauważalne ...
W języku niskim poziomie komputerowym: Normalne dodanie (zmienna: = zmienna1 + zmienna2) implikuje dwa odczyty w pamięci plus jedna suma plus e memory write ... dużo pracy Ale jeśli jest (zmienna: = zmienna + inna zmienna), może być zoptymalizowana przechowująca zmienna wewnątrz pamięci podręcznej procesora. Również jeśli jest to (zmienna: = stała1 + stała), można ją również zoptymalizować, utrzymując stałą wartość na pamięci podręcznej procesora. A jeśli tak (zmienna: = zmienna + stała), oba są buforowane na pamięć podręczną procesora, więc ogromnie szybkie porównanie przy innych opcjach nie jest potrzebny dostęp do pamięci RAM.
w ten sposób wstępnie kompilatora optymalizator zrobić kolejny ważny optymalizacji ... for-pętle zmienne indeksowe są przechowywany jako rejestry procesora ... dużo bardziej szybciej niż procesor cache ...
Most procesor matki zrobić dodatkowy optymalizacja (na poziomie sprzętowym, wewnątrz procesora) ... niektóre obszary pamięci podręcznej (dla nas zmienne 32-bitowe), które są intensywnie używane, są przechowywane jako rejestry specjalne w celu zapewnienia dostępu ... i takiej pętli for-loop/while Indeksy są jednym z nich ... ale jak powiedziałem .. większość procesorów AMD matka (te, które używa technologii MP robi to) ... nie znam jeszcze żadnego Intel, który to robi !!! taka optymalizacja jest bardziej odpowiednia w przypadku wielordzeniowych i superkomputerowych ... więc może to jest powód, dla którego AMD ma to i Intel nie !!!
Chcę tylko pokazać jedno "dlaczego", jest o wiele więcej ... inny może być tak prosty, jak indeks jest przechowywany w bazie danych typu pola Int64, itp ... jest wiele powodów wiem i jeszcze więcej nie wiedziałem jeszcze ...
Mam nadzieję, że pomoże to zrozumieć potrzebę zrobienia pętli na indeksie Int64, a także jak to zrobić bez utraty prędkości, poprawnie i sprawnie konwertując pętlę w pętla while.
Uwaga: W przypadku kompilacji x86 (nie w przypadku kompilacji 64-bitowej) należy pamiętać, że Int64 jest zarządzany wewnętrznie jako dwie części Int32 ... a podczas modyfikowania wartości istnieje dodatkowy kod do wykonania, w przypadku dodawania i podrzędnych jest bardzo niski, ale na mnożnikach lub podziałach takie dodatkowe są zauważalne ...ale jeśli naprawdę potrzebujesz Int64, potrzebujesz go, więc co jeszcze możesz zrobić ... i wyobrazić sobie, że potrzebujesz float lub double, etc ... !!!
Definiowanie "en error". – simchona
Nie mogę zobaczyć błędu. Również program nie można uruchomić .. – musti
+1, ponieważ jest to pytanie akademickie, widzę tak i tak zachowanie. Spodziewałam się, że zadziała, ale nie ... dlaczego tak się zastanawiam. Zamiast "naprawdę potrzebuję wykonać trylionów iteracji w moim rodzaju pętli". – Johan