Strona główna » Algorytmy » Planowanie Pracy Dysku » Algorytm C-SCAN
 

Algorytm C-SCAN

Wstęp

Algorytm C-SCAN optymalizuje działanie algorytmu planowania SCAN poprzez dodanie możliwości przeskoczenia na drugi koniec danych. Oczywiście ma to również wpływ na czas obsługi wszystkich zdarzeń. W tym artykule zostaną wskazane różnice między wersją C-SCAN, a SCAN oraz jak zaimplementować nowy algorytm.

Opis

Głowica dysku w algorytmie SCAN podróżowała w określonym kierunku obsługując napotkane żądania. Po dotarciu do brzegu kierunek głowicy zmieniał się na przeciwny. Jednak w przypadku algorytmu C-SCAN głowica po dotarciu na brzeg przeskakuje na przeciwny brzeg i nie zmienia kierunku. Takie rozwiązanie nie wpływa znacząco na czas obsługi żądań. Wiadomo, że głowica przechodzi przez wszystkie pozycje, więc w czasie jednego cyklu pewne jest, że żądanie zostanie obsłużone.

Załóżmy, że dysk składa się z 100 segmentów. Do kolejki przychodzą następujące żądania odczytania: {25, 35, 30, 60, 80, 40}. Początkowo głowica znajduje się nad segmentem 0 i będzie poruszać się "w górę". Schemat pokazujący skuteczność metody jest przedstawiony poniżej:

Algorytm C-SCAN

Algorytm wpierw przechodzi kolejno obsługuje żądania 25, 35, 60 oraz 80 następnie przechodząc do końca prawej strony głowica wraca na drugi brzeg i obsługuje pozostałe żądania.

W powyższym przykładzie głowica musi wykonać dokładnie 140 skoków. Nie jest to nadal najbardziej optymalna ścieżka. Jednak takie rozwiązanie gwarantuje, że każde żądanie zostanie obsłużone w trakcie jednego cyklu przejścia głowicy. Dzięki temu o wiele łatwiej jest przewidzieć np. na jak długo wykonywany program powinien zostać wstrzymany.

Analiza Zadania

Algorytm naśladujący algorytm C-SCAN musi przetrzymywać na bieżąco pozycję głowicy, a następnie wybierać kolejne żądania, które mają pozycję większą niż aktualną pozycję głowicy. Jeśli algorytm przejrzy wszystkie elementy tablicy to powinien zresetować pozycję głowicy na 0 i rozpocząć przeszukiwanie bufora żądań od nowa.

Implementacja

Kolejność

Funkcja KolejnoscCSCAN() zwraca dla podanej listy lokalizacji kolejność w jakiej żądania zostaną obsłużone. Opcjonalnie można ustawić poz - aktualną pozycję głowicy.

  1. static List<int> KolejnoscCSCAN(List<int> dane, int poz = 0) {
  2.   List<int> wynik = new List<int>();
  3.   List<int> bufor = new List<int>(dane);
  4.   int i = 0;
  5.   while (bufor.Count() > 0) {
  6.     if (bufor[i] > poz) {
  7.       wynik.Add(bufor[i]);
  8.       poz = bufor[i];
  9.       bufor.RemoveAt(i);
  10.     } else {
  11.       i++;
  12.     }
  13.     if (i >= bufor.Count) {
  14.       i = 0;
  15.       poz = 0;
  16.     }
  17.   }
  18.   return wynik;
  19. }

Algorytm działa w pętli, aż do usunięcia wszystkich żądań z bufora. Żądanie jest obsługiwane, a następnie usuwane tylko pod warunkiem, że aktualnie przeglądane żądanie ma pozycję zaraz po aktualnej pozycji głowicy. Należy pamiętać, aby indeks przeglądanego żądania zwiększyć tylko, gdy aktualne żądanie nie zostaje obsłużone.

Ilość skoków

W celu obliczenia ile skoków musi łącznie wykonać głowica należy wyznaczyć kolejność obsłużenia, a następnie obliczenia wartości absolutnej każdego kolejnego przesunięcia. W tym przypadku należy pamiętać, że jeśli kolejna pozycja jest mniejsza niż poprzednia to głowica musiała przejść do końca i dopiero od pozycji 0 do lokalizacji żądania.

  1. static int SkokowCSCAN(List<int> lokalizacje, int max, int poz = 0) {
  2.   int lacznie = 0;
  3.   List<int> dane = KolejnoscCSCAN(lokalizacje, poz);
  4.   for (int i = 0; i < dane.Count; i++) {
  5.     if (dane[i] > poz) {
  6.       lacznie += Math.Abs(dane[i] - poz);
  7.     } else {
  8.       lacznie += max - Math.Abs(dane[i] - poz);
  9.     }
  10.     poz = dane[i];
  11.   }
  12.   return lacznie;
  13. }

Testowanie funkcji

Algorytmy można przetestować przy pomocy poniższego fragmentu kodu:

  1. static void Main(string[] args) {
  2.   List<int> lokalizacje = new List<int>();
  3.   Console.WriteLine("Podaj lokalizacje:");
  4.   string[] dane = Console.ReadLine().Split(' ');
  5.   foreach (string s in dane) {
  6.     lokalizacje.Add(Convert.ToInt32(s));
  7.   }
  8.   Console.Write("Podaj zakres lokalizacji:\n max = ");
  9.   int max = Convert.ToInt32(Console.ReadLine());
  10.   List<int> kolejnosc = KolejnoscCSCAN(lokalizacje);
  11.   Console.WriteLine("Kolejność obsługi:");
  12.   foreach (int a in kolejnosc)
  13.     Console.Write("{0} ", a);
  14.   int lacznie = SkokowCSCAN(lokalizacje, max);
  15.   Console.WriteLine("\nPotrzebnych skoków: {0}", lacznie);
  16.   Console.ReadKey();
  17. }