Kilka tygodni temu świat obiegła wiadomość o eksperymencie, wskazującym na możliwość istnienia neutrin poruszających się z szybkością większą niż świetlna. Rzeczone cząstki zostały wykryte o około 60 nanosekund wcześniej niż powinny, co wskazywałoby na to, iż właśnie o tyle szybciej przebyły nieco ponad 700-kilometrową odległość między szwajcarskim a włoskim laboratorium.
Czy owe 60 nanosekund to długo? No cóż, przychodzą tu do głowy dwie skrajne odpowiedzi. Z jednej strony to bardzo długo: w tym czasie fala elektromagnetyczna przebiegnie jakieś 60 metrów, a niedokładność tego rzędu byłaby kilkakrotnie większa niż zwyczajnego odbiornika GPS w nowoczesnym telefonie. Z drugiej strony jest to oczywiście niewyobrażalnie krótkie mgnienie oka – ale tylko w sensie metaforycznym, bo to rzeczywiste trwa przecież miliony razy dłużej.
Bardziej interesujące jest, jak taki odcinek czasowy ma się do przedziałów czasu, z którymi możemy mieć do czynienia podczas programowania. O ile rzędów wielkości różnią się od niego typowe interwały, z którymi stykamy się w różnego rodzaju aplikacjach?
Okazuje się, że o całkiem sporo… albo o bardzo niewiele. Na każdym z poziomów pośrednich dzieje się jednak zawsze coś ciekawego.
Obecne temperatury są uciążliwe nie tylko dla nas – organizmów opartych o białka i węgiel, ale też dla naszych półprzewodnikowych, krzemowych gadżetów. Dotyczy to również komputerów oraz ich procesorów. Jak każde układy scalone, mają one tendencję do nagrzewania się – czasem nadmiernego. Dlatego dobrze jest monitorować temperaturę procesora.
Istnieje oczywiście wiele gotowych aplikacji, które na to pozwalają, ale przecież zawsze fajniej jest zakodować coś samemu, nieprawdaż? :) A już zupełnie świetnie jest wtedy, gdy użyjemy do tego naszego ulubionego narzędzia do administrowania systemem, czyli PowerShella.
Przy jego pomocy pobranie aktualnej temperatury procesora nie jest trudne. Posługujemy się do tego WMI – Windows Management Instrumentation – które to jest rozszerzeniem modelu sterowników systemu Windows, pozwalającym m.in. na monitorowanie różnego rodzaju informacji diagnostycznych. PowerShell zawiera wbudowane komendy, pozwalające na tworzenie obiektów WMI – wśród nich również takich, które udostępniają informacje na temat temperatury procesora:
Z bliżej nieokreślonych powodów wartość temperatury podawana jest w dziesiątych częściach kelwinów, więc konieczne jest ich przeliczenie na stopnie Celsjusza. Ponadto istnieje też prawdopodobieństwo, że używana tutaj klasa WMI o nazwie MSAcpi_ThermalZoneTemperature
nie jest dostępna na naszym komputerze – zależy to prawdopodobnie od modelu jego płyty głównej. W moim przypadku powyższy kod działał bez problemu na komputerze stacjonarnym, lecz nie na laptopie. Może to i dobrze… Mam bowiem uzasadnione przeczucie, że temperatura tamtejszego procesora wcale by mi się nie spodobała ;)
Niektóre funkcje dobrze jest pisać w asemblerze. Tak, wiem że dzisiaj – w epoce języków (zbyt) wysokiego poziomu – brzmi to dziwnie, ale to prawda. To najprostszy sposób na poprawienie wydajności często wykonywanych operacji, np. kalkulacji z użyciem wektorów i macierzy.
Rzecz w tym, że korzystając bezpośrednio z zaawansowanych możliwości oferowanych przez współczesne procesory, jednocześnie uzależniamy się od nich. Przykładowo, transformację wektora przez macierz można naturalnie po prostu przetłumaczyć z odpowiedniego wzoru na instrukcje jednostki zmiennoprzecinkowej i uzyskać kod działający na każdym procesorze. Jeżeli jednak użyjemy np. SSE2, możemy uzyskać kilkakrotny wzrost wydajności – lecz wówczas nasza funkcja będzie działała tylko na nowszych procesorach.
Najlepiej byłoby więc mieć kilka wersji takiej funkcji i wybierać odpowiednią dla procesora pracującego na danej maszynie. Jak jednak wykryć, co potrafi dana jednostka? Otóż z pomocą przychodzi nam system operacyjny. W Windows na przykład istnieje funkcja o wiele mówiącej nazwie IsProcessorFeaturePresent
, przy pomocy której możemy sprawdzić obecność rozszerzeń MMX, 3DNow!, SSE i SSE2.
Oczywiście, takiego sprawdzenia należy dokonać raz na początku działania programu. Jeśli jednak po prostu zapiszemy jego rezultat w formie globalnych flag boolowskich, to ich odczytywanie np. przy każdym dodawaniu wektorów będzie nie tylko kłopotliwe, ale i nieefektywne.
Lepszym rozwiązaniem jest stworzenie odpowiedniej liczby globalnych wskaźników na funkcje, inicjowanych w czasie uruchamiania programu; tak jak poniżej:
Dzięki temu zarówno w kodzie asemblerowym poszczególnych wersji (którego litościwie nie pokażę ;D), jak i wywołaniach, nie widać żadnego śladu po ‘magii’ wyboru funkcji dostosowanej do procesora. Narzut to rozwiązanie to naturalnie jedna dereferencja wskaźnika więcej; sprawdzanie flag (porównaniami i skokami) trwałoby znacznie dłużej.