Skip to content

Instantly share code, notes, and snippets.

@liquidev
Last active February 19, 2022 21:22
Show Gist options
  • Save liquidev/0b1f6f37a525ae7f3887dc8006da1a6b to your computer and use it in GitHub Desktop.
Save liquidev/0b1f6f37a525ae7f3887dc8006da1a6b to your computer and use it in GitHub Desktop.
Wyzwanie CIF

Wyzwanie CIF

Jeśli dotarłeś lub dotarłaś do tego pliku - gratulacje! Masz szansę wziąć udział w wielkim wyzwaniu CIF, w którym to nerdy biją się o to kto potrafi lepiej zoptymalizować program.

Wyzwanie polega na napisaniu najszybszego możliwie dekodera formatu CIF w dowolnie obranym przez siebie języku. Jeśli nie masz pomysłu, to proponuję jeden z poniższych:

Specjalnie wybrałem tutaj języki mniej znane, bo w wyzwaniu chodzi o to, żeby było… cóż, wyzwaniem, a niekoniecznie szlifowaniem skilli w językach które się już zna. Nauczenie się nowego języka ma dużo zalet, np. zobaczenie innych perspektyw na świat programowania, więc gorąco zachęcam.

Ja wybrałem C ponieważ spędzając czas głównie w językach dość nowoczesnych moje umiejętności programowania w C są niezbyt rozwinięte.

Składnia CIF

Oto definicja formalna składni CIF, zapisana w notacji PEG.

file ← magic version dimensions metadata pixels

flag ← 'polish'
flags ← flag (',' ws flag)*
magic ← 'CIF:' ws flags nl

version ← 'WERSJA' ws int nl

width ← 'szerokość:' ws int
height ← 'wysokość:' ws int
bpp ← 'bitów_na_piksel:' ws int
dimensions ← 'ROZMIAR' ws width ',' ws height ',' ws bpp nl

mdkey ← [^ ]
mdvalue ← [^\n]
metadatum ← 'METADANE' ws mdkey ws mdvalue nl
metadata ← metadatum*

pixel ← int ';' ws int ';' ws int (';' ws int)? nl
pixels ← pixel*

hundreds ←
  'sto' / 'dwieście' / 'trzysta' / 'czterysta' / 'pięćset' /
  'sześćset' / 'siedemset' / 'osiemset' / 'dziewięćset'
nteens ←
  'dziesięć' / 'jedenaście' / 'dwanaście' / 'trzynaście' /
  'czternaście' / 'piętnaście' / 'szesnaście' / 'siedemnaście' /
  'osiemnaście' / 'dziewiętnaście'
tens ←
  'dwadzieścia' / 'trzydzieści' / 'czterdzieści' / 'pięćdziesiąt' /
  'sześćdziesiąt' / 'siedemdziesiąt' / 'osiemdziesiąt' / 'dziewięćdziesiąt'
ones ←
  'jeden' / 'dwa' / 'trzy' / 'cztery' / 'pięć' /
  'sześć' / 'siedem' / 'osiem' / 'dziewięć'
zero ← 'zero'

thousand ← 'tysiąc'

thousands1pair ←
  (hundreds ws)? (tens ws)? ('dwa' / 'trzy' / 'cztery') ws 'tysiące'
thousands2pair ←
  (hundreds ws)?
  ((tens ws)? ('pięć' / 'sześć' / 'siedem' / 'osiem' / 'dziewięć') / nteens)
  ws 'tysięcy'
thousands ← thousand / thousands1pair / thousands2pair

int100 ←
  hundreds ws nteens /
  hundreds ws tens ws ones /
  hundreds /
  nteens /
  tens ws ones /
  tens /
  ones
int ←
  zero /
  thousands ws int100 /
  int100

ws ← ' '+
nl ← '\n'+

Symbole terminalne:

  • 'abc' - ciąg znaków - sprawdza dosłowny ciąg znaków w pliku
  • [abc] - zbiór znaków - sprawdza czy znak należy do zbioru
  • [^abc] - dopełnienie zbioru znaku - sprawdza czy znak nie należy do zbioru

Uprzedzam że nie testowałem powyższej specyfikacji i posiada ona charakter czysto poglądowy. Mogą się w niej znajdować drobne błędy.

Termin

Termin wysyłania dekoderów to 14 lutego 2022. Dekodery wysłane do mnie po terminie nie ukażą się w benchmarku.

Nagrody

Niestety w Polsce jest bieda aż piszczy więc za udział w wyzwaniu nie ma nagród pieniężnych. Za nagrodę możecie uznać swój udział, kod który napiszecie, oraz wynik w benchmarku. Jeśli będzie to implementacja szczycąca się w pewnych aspektach (szybkość, czytelność kodu, kompaktowość) to polecam dopisać ją sobie do portfolio.

Każdy kto się zgłosi z działającym, przechodzącym suitę testów dekoderem, zostanie umieszczony w filmie podsumującym, który powinien ukazać się w lutym (może się nie ukazać ponieważ jestem leniem, zwłaszcza gdy są ferie).

Zanim pojawi się film, wyniki benchmarku będą podane na tej stronie.

Zasady

  1. Dekoder musi być open source. Kod źródłowy nie musi być publiczny podczas trwania konkursu (nie sądzę aby ktokolwiek chciał zostać okradnięty z kodu), ale po minięciu terminu kod źródłowy musi zostać otwarty pod jedną z licencji wolnego oprogramowania.
  2. Dekoder musi być w stanie bezstratnie zdekodować dowolny obrazek CIF do pliku formatu BMP lub PNG.

Obrazki testowe

Obrazki testowe można znaleźć w repozytorium comes-group/cif-tests. Znajduje się tam również skrypt do automatycznego testowania dowolnego dekodera, który przydziela ocenę w zależności od tego ile testów przeszedł. Jeżeli ktoś dostanie dekoder z oceną Silver, to po terminie wysyłania dekoderów sprawdzę czy dekoder nadaje się do oceny Gold (nie próbuje obejść testów).

Benchmark

Benchmark wykonam po nadaniu ocen Gold dekoderom kwalifikującym się na tę ocenę. Będzie on wykonywany na różnych obrazkach które nie pochodzą z folderu cif-tests, więc dekodery powinny być przygotowane na wszystko.

Własne obrazki można generować enkoderem cif.nim. Nie jest on demonem szybkości, ale lepszy rydz niż nic. Swoją drogą cif.nim posiada również dekoder którego można użyć jako podstawę do napisania własnego, choć wątpię żeby przechodził wszystkie testy bez zająknięcia (nie sprawdzałem.)

Profesjonalne wskazówki optymalizacyjne

  • Używaj https://godbolt.org
  • Traktuj plik wejściowy jako strumień. Nie fragmentuj go na dalsze kawałki splitem czy też innymi funkcjami które alokują pamięć.
  • (Nad)używaj optymalizacji kompilatora. Zwłaszcza CSE (common subexpression elimination)
@liquidev
Copy link
Author

liquidev commented Jan 18, 2022

Cześć okej. To jest mój dekoder: https://github.com/liquidev/cif123

Pozdrawiam. Polecam. Oglądam.

PS. Tak naprawdę to mój dekoder zostanie upubliczniony [TODO: wstaw termin tutaj] 14 lutego 2022, jak skończy się konkurs. https://github.com/comes-group/djcifex

@lemon-sh
Copy link

oto moja abominacja
wydajność ssie, kod paskudny. buildować z rustc nightly.
uwaga: zaglądanie w perf stat grozi utratą stabilności psychicznej

Polecam serdecznie!

@ezioleq
Copy link

ezioleq commented Feb 14, 2022

https://git.ezioleq.com/Ezioleq/SMIER.CIFoverOXYGEN17-18-2020
nie wiem czy to dziala nawet, nie uruchamiaj tego prosze
to mialo inaczej wygladac, potrzebuje jeszcze troche... czasu...

@survivorr9049
Copy link

https://github.com/survivorr9049/comesparser
to mem nie umiem angielski nie umiem kod nie umiem niczego

@reticulis
Copy link

Cześć idol, mój dekoder: https://github.com/reticulis/cif , przechodzi testy z https://github.com/reticulis/cif-tests więc może coś podziała, z góry przepraszam za shitty kod ale "programuje na poważnie" od kilku dni

@liquidev
Copy link
Author

dobra jest już bo wczoraj zapomniałem XD
https://github.com/comes-group/djcifex

film będzie za jakiś czas.

@liquidev
Copy link
Author

Skończył się bandwidth LFS w cif-tests. Dokupiłem dodatkowe 50 GB na kolejny miesiąc w razie gdyby ktoś chciał ulepszyć parser w celu zgodności ze specyfikacją.

@liquidev
Copy link
Author

liquidev commented Feb 19, 2022

Postanowiłem opublikować wyniki bo znając mnie to film tak szybko nie wyjdzie. Zwłaszcza że zacząłem inną serię z nudów i teraz kompletnie nie chce mi się robić filmu z wynikami CIFa XD

Testy

  1. Gold
  2. Silver: –
  3. Bronze
  4. Non-compliant

Benchmark

Im mniejszy czas tym lepiej.

Dekoder Średnia [ms] Min [ms] Max [ms] Czas względnie
DJ Cifex 110.1 ± 0.7 108.6 111.4 1.00
zardzewialy-dekoder-cif 516.2 ± 8.1 506.0 531.3 4.69 ± 0.08
reticulis/cif 1587.5 ± 16.5 1568.4 1619.6 14.42 ± 0.18
SMIER.CIFoverOXYGEN17-18-2020 2042.2 ± 20.4 2009.4 2071.0 18.55 ± 0.22
comesparser 2619.4 ± 25.9 2592.0 2678.8 23.79 ± 0.28

Tutaj można znaleźć skrypty do reprodukcji testów: https://github.com/comes-group/cif-challenge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment