Optymalizacja FFdecsa

FFdecsa to szybka implementacja algorytmu deszyfrującego CSA dla pakietów MPEG TS. Algorytm ten jest używany w telewizji cyfrowej DVB do szyfrowania obrazu video. Korzystą z niego między innymi posiadacze kart DVB bez sprzętowego dekodera, którzy używają VDR do oglądania telewizji satelitarnej.

Jak podaje autor, jego implementacja jest ponad 800% szybsza niż najszybsza, którą znalazł. Wyjaśnia to nazwę programu, której skrót jest rowinięty w jednym z pytań w FAQ (dołączonym do źródeł). Dzięki takiemu wzrostowi wydajności zyskujemy między innymi następujące właściwości:

Autor zadbał o dobrą dokumentację swojego programu. Warto przeczytać dołączony do źródeł plik README oraz dokumnety w katalogu docs. Dostarczą nam one odpowiedzi na większość nasuwających się pytań ;)

Istnieją dwa sposoby optymalizacji FFdecsa. Przed kompilacją możemy wyedytować plik Makefile, aby dostosować flagi kompilatora. Podstawa to zmiana architektury procesora (-march). Drugą opcją jest zmiana strategii grupowania bitowego. Ma to ogromny wpływ na wydajność algorytmu, a nie jest trudne do wykonania. Wystarczy w pliku FFdecsa.c zmienić definicję PARALLEL_MODE. Dostępne wartości, z których możemy wybierać zdefiniowane są w tym samym pliku nieco wyżej.

Aby uzyskać najlepszą wydajność (oraz z ciekawości) skompilowałem FFdecsa dla każdego dostępnego wariantu PARALLEL_MODE. Po kompilacji można wywołać program FFdecsa_test, który przetestuje poprawność dekrypcji i oszacuje jej prędkość. Dla uzyskania lepszych rezultatów dobrze jest przeprowadzić testy na bezczynnej maszynie i podwyższyć priorytet zadania przy pomocy polecenia nice (alternatywnie można wywołać 'make test'):

nice -n -19 ./FFdecsa_test

Dla procesora AMD Athlon XP 2000+ (1,67MHz) uzyskałem poniższe wyniki.

PARALLEL_32_4CHAR6.79 Mbit/s4615.33 pkts/s
PARALLEL_32_4CHARA6.19 Mbit/s4211.85 pkts/s
PARALLEL_32_INT103.35 Mbit/s70216.50 pkts/s
PARALLEL_64_8CHAR7.95 Mbit/s5407.34 pkts/s
PARALLEL_64_8CHARA7.74 Mbit/s5258.37 pkts/s
PARALLEL_64_2INT36.58 Mbit/s24850.89 pkts/s
PARALLEL_64_LONG85.68 Mbit/s58208.91 pkts/s
PARALLEL_64_MMX132.96 Mbit/s90326.34 pkts/s
PARALLEL_128_16CHAR10.37 Mbit/s7050.85 pkts/s
PARALLEL_128_16CHARA4.54 Mbit/s3085.76 pkts/s
PARALLEL_128_4INT63.87 Mbit/s43391.91 pkts/s
PARALLEL_128_2LONG30.87 Mbit/s20975.88 pkts/s
PARALLEL_128_2MMX14.53 Mbit/s9874.25 pkts/s
PARALLEL_128_SSENaruszenie ochrony pamięci

Najlepszym wyborem (podobnie jak u autora) jest tryb PARALLEL_64_MMX. Prawdopodobnie będzie tak w przypadku większości procesorów. Tryb PARALLEL_32_INT nie okazał się wiele gorszym, a skoro jest bardziej przenośnym, często może być lepszym wyborem (dlatego jest wartością domyślną). PARALLEL_128_SSE spowodował naruszenie ochrony pamięci i w sumie nie bardzo wiem dlaczego (bug gcc? specyfika instrukcji sse w athlonie?). Polecam przeprowadzenie testów u siebie choćby dla kilku wyróżniających się trybów :D

Komentarze