Jak wykonywać operację kilka milionów razy na sekundę?

0

Piszę sobie emulatorek własnego wymyślonego 8-bitowego procka (coś a-la DCPU-16 Notcha), no i natknąłem się na problem jak wykonywać jakąś procedurę/funkcję wielokrotnie w ciągu sekundy. Procek ma być taktowany zegarem 3MHz, czyli będzie wykonywać 3000000 operacji na sekundę.

Mógłbym użyć TTimer, problem jednak w tym że z jego pomocą mogę "odpalać" funkcję max. tysiąc razy na sekundę (przy wartości interval:=1), a ja potrzebuję niestety robić to więcej razy. Nie mogę też użyć "normalnej" pętli, bo procek wtedy będzie taktowany... zegarem realnego procesora użytkownika, a ma być zawsze 3MHz. Jakieś pomysły jak to zrobić?

0

Zrób pętlę i licz, ile zajmuje wykonanie pojedynczej instrukcji, potem to przeliczaj i dodawaj jakiegoś sleep'a.

0

Tylko że nie za bardzo wiem jak (liczenie ile trwa pojedyncza instrukcja)). Jakiś konkretny przykład?

0

Najprościej to coś w tym rodzaju:

Var Time: Cardinal;
{...}
While (true) Do
Begin
 Time := GetTickCount;

 [wykonanie danej instrukcji, inkrementacja pozycji etc.]

 Time := GetTickCount-Time;
 [w zmiennej `Time` masz ile czasu trwa wykonanie pojedynczej instrukcji (w milisekundach)]
End;
0
Var Time: Cardinal;
    Factor: Integer;
{...}
While (true) Do
Begin
 Inc(Factor);
 Factor := Factor mod 1000; //może być inna liczba, zamiast 1000;
 if Factor = 0 then Time := GetTickCount;

 [wykonanie danej instrukcji, inkrementacja pozycji etc.]

 if Factor = 0 then 
   begin
     Time := GetTickCount-Time;
      //w zmiennej `Time` masz ile czasu trwa wykonanie pojedynczej instrukcji (w milisekundach)]
   end;
End;
0

Zamiast GetTickCount lepiej Jak zmierzyć czas wykonywania operacji poza tym trochę niezbyt udana nazwa zmienne Time.

0

@kAzek, od 2002 roku minęło trochę czasu, teraz używa się metod QueryPerformanceCounter/QueryPerformanceFrequency

0

teraz używa się metod QueryPerformanceCounter/QueryPerformanceFrequency

To po pierwsze, używaj tego jeżeli chcesz mieć dokładne odstępy.

  1. Zrób pętle w której dajesz sleepa zależnego od tego czy mamy nadmiar czasu czy niedoczas.
  2. Licz ile czasu mineło od ostatniego wykonania naszej procedury z naszej pętli, wyliczaj ile to będzie taktów twojej maszyny i wykonuj ich tyle.
  3. W twojej pętli wykonuj conajmniej parę razy na sekundę Application.ProcessMessages co spowoduje że twoja appka wykona bieŻące zadania i odda ci kontrolę - tak możesz robić nieblokujące pętle.

A jeżeli potrzebujesz naprawdę szybkiego wykonania to można się pokusić o TThread ale to wyższa szkoła jazdy.

Patryk27 napisał(a)

Wtedy mamy jeszcze instrukcję rdtsc.

RDTSC jest niebezpieczne z paru powodów: Teoretycznie możliwe jest że w zależności od tego który procesor wykona twoje polecenie inna będzie wartość RDTSC - Musisz skojarzyć swój wątek z jednym procesorem. Poza tym współczesne systemy dysponują dokładniejszymi pomiarami np. na płycie głównej które można odczytać poprzez WinAPI.

0

No niestety, ale WinAPI całkowicie odpada, bo chcę mieć przenośny kod, aby później skompilować pod Linuksa, itp.

0
Darkhog napisał(a):

No niestety, ale WinAPI całkowicie odpada, bo chcę mieć przenośny kod, aby później skompilować pod Linuksa, itp.

To poszukaj przenośnych biblotek do dokładnego mierzenia czasu, reszta J.W.

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