Tworzenie projektu... czyli powstanie i ewolucja Enigma@Home

Zaczęty przez TJM, 27 Lipiec 2007, 16:22

TJM

Jakiś tymczasowy błąd w obliczeniach musiał wystąpić.
A to z home.php występuje od dawna, nie mam pojęcia czemu skrypt lubi sobie zgubić połączenie znienacka.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

AiDec

Ja tak tylko informacyjnie:

Dzisiaj, 30.05.2009 9:34 Scheduler request failed: HTTP internal server error.


Kilka sekund pozniej poszlo bez problemu.



Bo jest paru kumpli :),
Bo jest parę w życiu dobrych chwil...


Moja wizytowka i sygnaturka

TJM

Ten błąd pojawia się jak obciążenie serwera jest chwilowo bardzo duże (powyżej load 10.0) - FastCGI schedulery wtedy się poddają i kończą pracę z errorem 500, może to i lepiej bo serwera nie da się totalnie przeciążyć.
W nocy podobno były spamerskie ddosy na niektóre projekty i zakładanie setek spamerskich kont (a przynajmniej próby), u siebie dużych problemów nie widziałem, ale właśnie przy przedpołudniowej kawce kasuję dziesiątki kont typu 'buy viagra'  :ph34r:

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

Pigu

w lhc potwierdzam - pozakładane pierdylion kont, z 5 razy odbijałem wieczorem uotd co by mi myboinc zaliczył %)

edit:
2009-05-30 12:44:59|Enigma@Home|Sending scheduler request: Requested by user.  Requesting 2602986 seconds of work, reporting 1 completed tasks
2009-05-30 12:45:04|Enigma@Home|Scheduler request completed: got 0 new tasks
2009-05-30 12:45:04|Enigma@Home|Message from server: (Project has no jobs available)

w serwer status są :(

TJM

Właśnie nie wiem co jest grane, podłubałem rano w feederze i teraz coś się dziad zacina. To właśnie jest 'stabilność' ostatnich wersji serwera, a tu jeszcze dziś czytałem na grupie, że chcą promować je już jako server_stable %)


W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

AiDec

Cytat: TJM w 30 Maj 2009, 11:08
Ten błąd pojawia się jak obciążenie serwera jest chwilowo bardzo duże (powyżej load 10.0) - FastCGI schedulery wtedy się poddają i kończą pracę z errorem 500, może to i lepiej bo serwera nie da się totalnie przeciążyć.

Swietnie. Najlepsze rozwiazanie he he :).

Mialem poprzednio jedynie 3 sekundy zeby sie odezwac, tak wiec zamiescilem info o wydarzeniu bez zadnego komentarza. Wyszedlem z zalozenia ze lepiej Cie trzy razy poinformowac o pierdolce, niz raz nie poinformowac o powaznym bledzie. Nie oczekiwalem wlasciwie zadnego wyjasnienia, ani czegokolwiek innego poza ew. krotkim `All OK` :P. Serwer faktycznie mial prawo kleknac (chyba), bo doslownie chwile wczesniej odeslalem jakies 500 nieprzeliczonych junitow.



Bo jest paru kumpli :),
Bo jest parę w życiu dobrych chwil...


Moja wizytowka i sygnaturka

TJM

Pojedyńczy host nie ma prawa w żaden sposób przeciążyć serwera. Przeciążenia zdarzają się jedynie wtedy, kiedy w tym samym czasie zderzy się kilka requestów od hostów z ogromniastymi buforami. Jeśli host ma na zapleczu 1000+ zadań to zapytanie do bazy trwa trochę czasu, więc jeśli zderzy się takich kilka czas lawinowo rośnie.
Dzisiaj kurcze z deszczu pod rynnę, wczoraj naprawiłem jakiś problem z feederem (tzn tak mi się wydaje, przynajmniej działa), to dziś z kolei problem z file upload handlerem - cały czas pasowała mu nazwa 'fuh' a teraz nagle przestała. Jak widać BOINC ma wiele tajemnic %)

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

155kpol

Czyżby jakaś burza była? bo serwer nie chce gadać

EDIT: o działa ,super :)

TJM

To nie burza, tylko moja pomyłka %)
Myślałem, że ustawienie MaxClients na proxy trochę niżej w ładny i przyjemny sposób ograniczy liczbę połączeń, które czasami wiszą przez kilkanaście minut na Keep-Alive.
A tu się tymczasem okazało że z niższymi ustawieniami proxy nie może się łączyć nawet z lokalnym serwerem (download mirrorem) po localhoście.
Co gorsza, początkowo wszystko ładnie działało więc to tak zostawiłem, a kiedy zaczęło się sypać nie miałem zbytniego dostępu do serwera - poprawiłem dopiero po powrocie do domu.

Problem z file upload handlerem też się wyjaśnił w międzyczasie na liście mailingowej boinc_projects. Otóż okazuje się, że upload handler może mieć dowolną nazwę, pod warunkiem że jest to file_upload_handler, file_upload_handler albo ewentualnie file_upload_handler. No, ostatecznie file_upload_handler też może być. Trochę to dziwne, nigdy bym się nie spodziewał takiego czegoś  XD

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

sesef

Dzisiaj przeglądając sobie strone NV trafiłem na coś takiego

http://www.nvidia.com/object/cuda_home.html#state=detailsOpen;aid=61950ddf-e994-4823-a034-9b92880a62f9

Ma się to jakoś do projektu?

Szopler

Contact:
Cong-Van Nguyen
Department of Electronic Engineering
La Trobe University, Bundoora, Victoria 3083, Australia
c11nguyen@students.latrobe.edu.au
congvannguyen@yahoo.com

TJM

Bomba Turinga to zupełnie inny algorytm, można powiedzieć interaktywny, bo wymaga danych od użytkownika. Raczej do obliczeń rozproszonych mało przydatny, bo runtime jest dość krótki (kiedyś testowałem na PIV 1,4GHz i leciało od 30 minut do 2h na pojedyńczym cribie) i zwykłym przeciętnym pecetem szybko się wyczerpie zasób potencjalnych cribów.
Co innego ta symulacja, jej części może udałoby się wykorzystać do budowy aplikacji CUDA (częścią algorytmu jest próba odszyfrowania tekstu przy użyciu aktualnych ustawień czyli jakby symulacja pracy maszyny).

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

lukaszde

http://enigmaathome.net/server_status
Widac, ze po zakonczeniu probek hceyz72 wzrosl error rate

TJM

Prawdopodobnie dlatego, że jakaś część podłączonych komputerów ma bardzo stare app_info bez nowszej aplikacji, takie po prostu wysypują z miejsca wszystkie zadania.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

TJM

Poprawiłem dziś dość poważny bug, który bezczelnie powodował, że niektóre zadania nigdy nie miały chęci się pobierać a w innych czasami znienacka wskakiwały validation errory. Wszystko przez konwersję z długich ciągów liczb na ciągi liczbowe i z powrotem, jedna z funkcji miała błąd przez co niektóre ciągi liczb były kodowane z błędem.


W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

TJM

Rozmawiałem z gościem, który testował na GPU algorytm podobny do tego, ktorego używa aplikacja Stefana Kraha - czyli jakąś odmianę hillclimba.
Rezultaty nie są zbyt zachęcające, zbyt wielu szczegółów nie udało mi się uzyskać bo koleś jest dość trudno osiągalny i nie dysponuje nadmiarem czasu, więc ciężko coś z niego wydobyć. W każdym razie z jego testów wynika, że algorytm wypada kiepsko na kartach graficznych, średniej klasy karty wypadają znacznie gorzej od CPU łykając przy tym dużo więcej prądu, co niejako je dyskwalifikuje.
Zastanawia mnie tylko czy i ewentualnie w jaki sposób puszczał jakieś równoległe wątki na karcie, czy też może po prostu odpalał jakąś jednowątkową wersję algorytmu, co by od razu wyjaśniało kiepską wydajność.

Normalnie workunit wygląda np tak:

B164:AA:AAAA~B164:AZ:ZZZZ

można to potraktować jako licznik, każda z literek od prawej do lewej będzie przeskakiwać kolejno od początku zakresu do końca przez wszystkie możliwe ustawienia: skrajne z prawej zawsze od A do Z, natomiast środkowe to ringi i zależnie od użytych rotorów jest 13 (A-N) lub 26 (A-Z) ustawień. Z lewej są rotory ustawione na sztywno, teoretycznie da się i rotory kolejno sprawdzać ale jest to bardziej skomplikowane i o wiele trudniej weryfikuje się poprawność wyników.
Podczas liczenia na CPU jednym wątkiem, dla każdego ustawienia wykonywane są pewne powtarzające się czynności:
wybierana jest kolejna pozycja startowa z zakresu, po czym program zaczyna od wygenerowania losowego steckera który potem jest losowo 'poprawiany', po każdej poprawce oblicza się 'score' dla rezultatu, jeśli jest lepszy zachowuje się zmianę, jeśli gorszy cofa i próbuje z innymi ustawieniami. Proces powtarzany jest kilkukrotnie, używając kolejno 3 metod obliczania score: ic-score (dane statystyczne), biscore i triscore (wartości oparte o słowniki zbitków 2 i 3 liter).
Najlepszy wynik jest zachowywany wraz z ustawieniami i jest to jedyna wartość jaką pamięta program, reszta jest odrzucana.

Stąd teoretycznie na GPU można od razu strzelić z grubej rury, podzielić otrzymany wraz z WU zakres na dowolną ilość mniejszych i pracować nad nimi równolegle, o ile przyniesie to jakiś wzrost wydajności. W takim wypadku koniecznie trzeba jedynie między wątkami jakoś dzielić aktualny najlepszy wynik, no i pilnować, żeby ewentualny dobry wynik nie został jakoś nadpisany gorszym o ile np. dwa wątki w tym samym momecie stwierdzą, że poprzedni jest gorszy od tego co znalazły. Nie wiem jak wygląda synchronizacja danych między wątkami na GPU, na CPU nie jest to zbyt trudne i z łatwością można by napisać multi-threaded enigmę, ale jest bo bez sensu bo wygodniej po prostu odpalić kilka procesów.
Zastanawia mnie też, czy taki numer (tzn odpalenie kilku niezależnych progsów) przejdzie również w przypadku GPU ? Podziału WU można dokonać w dowolnym momencie, serwer zamiast jednego długiego może wysłać 10 krótkich do odpalenia równolegle na grafie, rezultat będzie taki sam - jeden wynik będzie najlepszy, 9 będzie gorsze, tylko normalna aplikacja sama odrzuciłaby 9 i oddała 1 do serwera.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

sesef

Cytat: TJM w 15 Lipiec 2009, 22:56Zastanawia mnie też, czy taki numer (tzn odpalenie kilku niezależnych progsów) przejdzie również w przypadku GPU ? Podziału WU można dokonać w dowolnym momencie, serwer zamiast jednego długiego może wysłać 10 krótkich do odpalenia równolegle na grafie, rezultat będzie taki sam - jeden wynik będzie najlepszy, 9 będzie gorsze, tylko normalna aplikacja sama odrzuciłaby 9 i oddała 1 do serwera.

Takie rozwiązanie byłby najprostsze, ale wtedy następuje 1 problem mianowicie checkpointy, chyba że jesteś w stanie wygenerować wu, które da się podzielić na ~5k mniejszych i na tyle długich żeby np taki pentium III 800-1000 mhz liczył takie jedno małe WU koło minuty.

BTW. Większych zakresów liczbowych niż 32 bit w enigmie nie ma?

TJM

WU są dowolnie skalowalne, najlepszy wynik zawsze jest tylko jeden i reszta to teoretycznie śmieci. Z tym że dla każdego wysłanego rezultatu serwer trzyma zwrócony wynik, więc dzieląc po stronie serwera WU otrzymuję więcej wyników. Za bardzo nie można szaleć, bo nawet z normalnymi WU bazy wychodzą ogromne.
Można by jednak na potrzeby GPU stworzyć dwustopniową aplikację, która otrzymuje normalny, długi WU od serwera i sama dzieli go na kilka mniejszych, odpala właściwe aplikacje przeliczające i zwraca najlepszy wynik do serwera.

Najmniejszy możliwy workunit to coś typu B164:AA:AAAA~B164:AA:AAAB i jest to praktycznie niezmierzalny czas przeliczania (ułamki sekundy dla byle proca). Można go dowolnie wydłużać np. B164:AA:AAAA~B164:AA:AAZZ jest już 26*26 dłuższy.

Jedyną dużą liczbą w całym programie jest score, bi- i triscore zależą użytych słowników i długości tekstu, zazwyczaj mieszczą się jednak w zwykłym INT, dla słownika '1941' nawet spokojnie w unsigned mediumint dla bardzo długich tekstów (według typów danych MySQLa), bo po prostu mniejsze liczby są przypisane do ciągów znaków w tym słowniku.
ic-score chyba nie mieści się w zwykłym INT, stąd na końcu funkcji jest dzielenie żeby się zmieścić w sensownym zakresie, jednak czy zamiana tej jednej liczby na 64 bitową i rezygnacja z dzielenia coś zmieni nie sprawdzałem.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

TJM

Trzeba jakoś specjalnie definiować liczbę jako 64 bitową ?
Po samym usunięciu dzielenia program niestety sypie się w niektórych przypadkach (np. benchmarkowy testcase), więc prawie na pewno następuje przepełnienie zwykłego INTa.
Jednak moje doświadczenie z 64 bitami jest delikatnie mówiąc nienajlepsze (żeby nie powiedzieć żadne %)), stąd nie wiem co zrobić, żeby to działało i przy tym zgodne było z jakimiś standardami.
Dzielenie jest dość czasochłonne, więc jest szansa że usunięcie go z funkcji która jest jedną z głównych w programie powinno coś pomóc. Prawie na pewno program przyspieszy o kilka-kilkanaście procent, przyspieszenie to widać nawet zastępując oryginalną funkcję ic-score inną, bardziej skomplikowaną ale jednocześnie bez końcowego dzielenia (niestety generującą przy tym niekompatybilne wyniki, więc nie można ich używać zamiennie).


W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

sesef

Cytat: TJM w 18 Lipiec 2009, 20:56
Trzeba jakoś specjalnie definiować liczbę jako 64 bitową ?
Po samym usunięciu dzielenia program niestety sypie się w niektórych przypadkach (np. benchmarkowy testcase), więc prawie na pewno następuje przepełnienie zwykłego INTa.
Jednak moje doświadczenie z 64 bitami jest delikatnie mówiąc nienajlepsze (żeby nie powiedzieć żadne %)), stąd nie wiem co zrobić, żeby to działało i przy tym zgodne było z jakimiś standardami.
Dzielenie jest dość czasochłonne, więc jest szansa że usunięcie go z funkcji która jest jedną z głównych w programie powinno coś pomóc. Prawie na pewno program przyspieszy o kilka-kilkanaście procent, przyspieszenie to widać nawet zastępując oryginalną funkcję ic-score inną, bardziej skomplikowaną ale jednocześnie bez końcowego dzielenia (niestety generującą przy tym niekompatybilne wyniki, więc nie można ich używać zamiennie).

A co chcesz zrobić? może masz problem typu że mnożysz jakąś liczbą, która jest typu 32bit przez stałą co w wyniku da już liczbę 64bit. Kompilator nie jest w stanie tego sprawdzić więc przyjmuje że wynik takiego mnożenia będzie 32bit nawet jak wynik takiego działania przypisujesz do typu 64 bit;

Przykład:

int64_t x; //64 bitowa liczba wynikowa
int32_t y; //32 bitowy liczba

x = y * 2147483647LL; //zamiast dopisywać LL do stałej można rzutować y na int64_t x = (int64_t)y * 2147483647;

wynikiem takiego działania jeżeli y != 0 na pewno będzie liczba 64 bit jednak jakbyśmy zapisali to tak x = y * 2147483647; to wynik będzie 32 bitowy pomimo tego że x został zadeklarowany jako 64bit. Niektóre kompilatory (może wszystkie) tak maja, że jak mu nie pokażesz, że chcesz 64 bit to tego nie zrobi

TJM

W progsie jest pętla w której wynik powstaje przez kilka(naście) -> n kolejnych mnożeń, a że powstająca liczba jest okrutnie wielka, zastosowane jest tam też dzielenie (przez n właśnie), dzięki czemu mieści się w rozsądnym zakresie.
Dążę do tego, żeby ta liczba mogła być okrutnie wielka (czyli w praktyce 64 bitowy INT), wtedy obejdzie się bez dzielenia, czyli powinno to zaoszczędzić trochę czasu procesora.
Teraz jednak pojawia się pytanie: czy dla 64 bitowego procesora, aplikacji i systemu działania na 64 bitach będą równie szybkie jak na 32 ? W aplikacji ewentualnie powstający 64 bitowy wynik będzie ciągle porównywany z innymi (najlepszy jest przechowywany), więc jeśli okaże się, że porównanie dwóch 64 bitowych liczb jest wolniejsze niż dla 32 bitowych, to przyrost prędkości aplikacji może okazać się ujemny...
Jeszcze muszę luknąć jak to wygląda w oryginalnych źródłach obecnejaplikacji, bo to w czym obecnie dłubię to stara i dużo wolniejsza wersja, ale przez to lepsza do testów, bo wszelkie zmiany są bardziej widoczne.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

sesef

Cytat: TJM w 18 Lipiec 2009, 23:31W progsie jest pętla w której wynik powstaje przez kilka(naście) -> n kolejnych mnożeń, a że powstająca liczba jest okrutnie wielka, zastosowane jest tam też dzielenie (przez n właśnie), dzięki czemu mieści się w rozsądnym zakresie.
Dążę do tego, żeby ta liczba mogła być okrutnie wielka (czyli w praktyce 64 bitowy INT), wtedy obejdzie się bez dzielenia, czyli powinno to zaoszczędzić trochę czasu procesora.
Teraz jednak pojawia się pytanie: czy dla 64 bitowego procesora, aplikacji i systemu działania na 64 bitach będą równie szybkie jak na 32 ? W aplikacji ewentualnie powstający 64 bitowy wynik będzie ciągle porównywany z innymi (najlepszy jest przechowywany), więc jeśli okaże się, że porównanie dwóch 64 bitowych liczb jest wolniejsze niż dla 32 bitowych, to przyrost prędkości aplikacji może okazać się ujemny...
Jeszcze muszę luknąć jak to wygląda w oryginalnych źródłach obecnejaplikacji, bo to w czym obecnie dłubię to stara i dużo wolniejsza wersja, ale przez to lepsza do testów, bo wszelkie zmiany są bardziej widoczne.

Porównanie liczb 64 bit na procesorze x64 to praktycznie to samo co porównanie liczb 32 bit na procku 32 bit. Po to powstało rozszerzenie x86_x864 żeby operacje na dużych liczbach 64 bit robić jedną instrukcją, a nie jak to ma miejsce na 32 bitowym procku przy pomocy kilku instrukcji. Zmień deklaracje zmiennej wynikowej na unsigned long long (deklaracja standardowa dla linuxa i windowsa) a przy wszystkich składnikach z których powstaje ten wynik dodaj dodatkowo przed zmienna rzutowanie na 64 bit (unsigned long long) i powinno działać. Pozbycie się dzielenia na x64 powinno przyspieszyć liczenie, na systemie x86 nie koniecznie, teoretycznie powinno być nawet wolniej z dzieleniem.

TJM

Dłubałem dziś sporo przy aplikacji, testowałem wydajność głównie pod linuksem ze względu na dostęp do 4 kompilatorów - 2 wersje gcc, Intel i Open64.
Wyżej wspomniane kombinowanie z 64 bitami ma sens raczej tylko jako dodatek do innych optymalizacji. Samodzielny przyrost prędkości jest raczej mizerny, na dodatek 64 bitowe kompilacje na procesorach Intela są po prostu wolniejsze od starych aplikacji zbudowanych przy użyciu gcc 3.2, tak więc nawet z przyspieszeniem po usunięciu paru drobiazgów przyrost prędkości przy przesiadce 32->64bit jest ujemny.

Nie rozumiem jednak wielu rzeczy. Na przykład tego:


  s0 = s1 = s2 = s3 = 0;
  for (i = 0; i < len-15; i += 16) {
    c1 = stbrett[ciphertext[i]];
    c1 = path_lookup[i][c1];
    c1 = stbrett[c1];
    s0 += unidict[c1];

    c2 = stbrett[ciphertext[i+1]];
    c2 = path_lookup[i+1][c2];
    c2 = stbrett[c2];
    s1 += unidict[c2];
[.....]
[.....]
[.....]
    c3 = stbrett[ciphertext[i+2]];
    c3 = path_lookup[i+2][c3];
    c3 = stbrett[c3];
    s2 += unidict[c3];

    c4 = stbrett[ciphertext[i+3]];
    c4 = path_lookup[i+3][c4];
    c4 = stbrett[c4];
    s3 += unidict[c4];
  }
  for (; i < len; i++) {
    c1 = stbrett[ciphertext[i]];
    c1 = path_lookup[i][c1];
    c1 = stbrett[c1];
    s0 += unidict[c1];
  }

  return (s0+s1) + (s2+s3);


Score które jest zwykłą sumą liczone jest na 4 zmiennych i na sam koniec po prostu sumowane. Oczywiście można wywalić te 4 zmienne i zostawić jedną, odpada też wtedy suma na końcu, ale pojawiają się ciekawe efekty:

-na procesorach typu PIII i pochodnych ogromny spadek wydajności
-na Athlonach 64/64 x2 lekki przyrost wydajności (rzędu 2%)
-na architekturze c2d nie widać zmian

Na dodatek dużo zależy tu od kompilatora, z tego co pamiętam właśnie z tym oryginalnym kodem na 4 zmiennych aplikacja skompilowana kompilatorem Intela na linuksie po prostu zmiata wydajnością wszystkie inne, wydajność jest tak ogromna, że gdyby istniały 4GHz PIII byłyby to najprawdopodobniej najlepsze procesory w projekcie - wydajność z każdego MHz lepsza jest chyba tylko na najmocniejszych C2D.

Z tego co czytałem w podręczniku kompilatora Intela, dość możliwe jest, że takie rozbite niezależne działania procesor jest w stanie wykonywać jednocześnie. Ale nie tłumaczy to, dlaczego w takim razie aplikacja zbudowana pod C2D, PIV czy inne nowsze procesory działa tak samo szybko, niezależnie od tego czy operuje na jednej zmiennej czy na czterech. Próbowałem nawet na 8 i 16 ale zmian nie widać.

Kolejna sprawa to tajemnicze -fschedule-insns na procesorach AMD.
Na procesorach Intela najwyższą wydajność uzyskuje się przez ręczne rozwinięcie kodu, tzn wszystkie wywołania drobniejszych funkcji zastępuję po prostu tą funkcją wklejoną w miejsce wywołania. Kod źródłowy jest po takiej akcji kobylasty, a plik wykonywalny wielki jak drzwi od stodoły, ale przyspieszenie na procesorach klasy c2d rzędu 10-15% więc nie do pogardzenia. Tak działa obecnie używana aplikacja dla c2d.
Na procesorach AMD jednak taki numer nie przechodzi, bo gcc wywala błędy przy próbie kompilacji tak rozwiniętego kodu z flagą -fschedule-insns, która jak zostało udowodnione jest kluczowa dla wydajności na prockach AMD. Bez tej flagi kod się kompiluje, ale zysk prędkości biorący się z braku wywołań funkcji zatraca się poprzez stratę wydajności przy braku -fschedule-insns. Z Open64 i rozwiniętym kodem również były jakieś zgrzyty kompilacji.

Jedno jeszcze mnie dziwi - na forum projektu mdoerner zarzucił kompilacje z Open64 m.in. właśnie dla Athlona 64 i 64x2 - te jego exeki chodzą w miarę przyzwoicie, śmiem nawet przypuszczać, że są to obecnie najszybsze dla tych Athlonów pod 32 bitowe systemy.
Jednak dziś próbowałem wykrzesać coś więcej z tego kompilatora i choćbym na rzęsach chodził po suficie nie mogłem uzyskać nawet zbliżonego wyniku; co więcej nie mogłem nawet uzyskać wyniku zbliżonego do byle chłamowatej kompilacji z gcc... Średnia kiepskich gcc-buildów w benchmarku którego dziś używałem (krótki, żeby nie zasnąć oczekując) to 24s, podobną wydajność osiągał exek skomplilowany Intelem z flagami generic x86 tak żeby progs działał również na AMD. Najszybszy exek z Open64 jaki udało mi się wykrzesać osiągnął 28s i co ciekawe, obojętnie jakie opcje bym do kompilacji nie dodawał czas ten znacznie się nie zmienia - są praktycznie tylko dwa stany: 1) progs się kompiluje i osiąga te 28s 2) wyskakuje błąd informujący o złych opcjach albo błąd kompilacji po włączeniu jakiejś opcji. WTF ?

Wygląda na to, że w źródłach czai się jeszcze spora rezerwa prędkości do wyciśnięcia, tylko trzeba porzucić jedno, wspólne źródło i spróbować z co najmniej dwoma róznymi wersjami: Intel/AMD lub co gorsza jeszcze jakieś wersje pośrednie, bo podejrzewam, że między Athlonami a Phenomem też różnice będą spore...

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

buninek

#983
Duży mankament, to niemożność rozsyłania optymalek do konkretnych CPU bezpośrednio przez serwer.

W tym projekcie brakuje tylko jeszcze jednej dobrej optymalki. Dla procesorów amd liczących pod windowsem.

Kiedyś przeglądałem statystyki hostów i jest tam całe stado amd x2 6000. Akurat liczyłem na swoim x2@2700 i
średnio miałem prawie 70% lepsze czasy. Różnica znaczna.

Zbudowanie może być trudne. Pewnie byłaby szybka, jeśliby udałoby się użyć  mingw (64-bit) z -fschedule-insns
(małe szanse). Wtedy mógłbyś na siłę je wcisnąć z serwera na te kompy. :D

Build mdoernera, kompilowany open64 testowałem. W moim przypadku wolniejszy o kilka %.
Choć ta aplikacja w przypadku procesorów phenom i nowszych procków ze stajni amd może wyppadać lepiej.

Jeśli masz ochotę możesz jeszcze testnąć moją aplikację (gcc-3.4.6) dla amd. Działa pod 64-bitowym systemem.
http://files.getdropbox.com/u/349831/enigma.static.x86_64.tar.bz2

TJM

Oprócz tego, że 'brakuje' aplikacji Windows/AMD, wszystkie inne da się przyspieszyć modyfikując źródła pod konkretny procesor i używając właściwych flag. Niestety, kombinacji jest łącznie tyle, że po paru godzinach zabawy już się nie pamięta co z czym i jak łączyć. Trzeba by jakoś usystematyzować wiedzę i wprowadzać kolejne zmiany w źródłach, sprawdzać na każdym procku jakie są efekty i kompilować z różnymi flagami.
Aplikacji 64 bitowej pod AMD chwilowo nie przetestuję, bo nie mam pod ręką kompa z Athlonem i 64bitowym systemem.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

X X X

Tak a`propos - mam AMD Phenom x4 9650 + Win7/64 i chętnie coś potestuję. A na tę chwilę mam krótkie pytanie - który z exe z poniższego linku użyć do mojego procka?
http://www.enigmaathome.net/forum_thread.php?id=17&nowrap=true#1166

TJM

Nie wiem, wypadałoby zrobić benchmark i po prostu wybrać najszybszy. Gdzieś na poprzednich stronach tego wątku jest opis jak wykonywać pomiary. Sprowadza się to do uruchomienia exeka z odpowiednimi parametrami i sprawdzenia ile czasu procesora użył do momentu zakończenia pracy.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

TJM

Wygląda na to, że pojawiły się jakieś nowe optymalizacje które nie są publicznie dostępne. Przypominają to co kiedyś sam skleciłem - aplikacja działa super szybko, ale niektórych zadań nie jest w stanie przetworzyć.
Przez to ładne parędziesiąt godzin przesiedziałem ostatnio poprawiając logikę assimilatora i validatora. Wcześniej zadania zweryfikowane jako błędne przetwarzane były przez główny serwer (to co siedzi 'nad' BOINCem, jako łączność z serwerem M4). Niestety rosnąca liczba nieprawidłowych rezultatów zaczęła mi zakłócać działanie tego systemu, do tego stopnia, że w tabelach aktywnych zadań chwilami wisiało po 500-600 tysięcy workunitów, które w BOINCu po kilka razy z rzętu trafiały na hosty nie będące w stanie ich przetworzyć. Są nawet hosty z aplikacjami które w ogóle nic nie są w stanie przeliczyć (nie wiem jak to w ogóle możliwe), a mimo to są podpięte i codzień kaszanią swoją dzienną dawkę zadań.

W związku z tym wprowadziłem duże zmiany - dla użytkowników ze sprawnie działającymi aplikacjami zmian praktycznie nie ma, oprócz tego, że nie można sobie resetować daily quota.
Wcześniej serwer 'wybaczał' drobne błędy i wysypanie się workunita raz na jakiś czas po prostu ignorował, nie obniżając daily quota. To dlatego, że błędne próbki w żaden sposób nie są w stanie wpłynąć na działanie całości, a wiadomo, że zdarzają się z różnych powodów - nadmierne O/C, jakiś zwisek systemu czy coś.
Teraz jest to zrobione na trochę innej zasadzie - dla hostów które przez dłuższy czas zwracały poprawne rezultaty, dalej stosowana jest polityka 'przymykania oka' na pojedyńcze błędy. Za to dla hostów, które regularnie zwracają dużą liczbę błędnych zadań limity są zaostrzone - daily quota leci lawinowo w dół, aż do momentu kiedy zwrócenie nawet jednego zadania z błędem automatycznie odcina hosta na następne 24h (daily quota od razu wskakuje na 1). Po kilku dniach działania nowego systemu kilka hostów już się na to załapało (nikt z naszego teamu).

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

X X X

To ciekawa informacja. A jak do tego mają się zadania przerwane przez użytkownika? Jestem "karany" za coś takiego, czy jest to neutralne? Chodzi mi o ogólną zasadę, nie tylko o ustawy Enigmy.

Jestem tu nowy i wciąż eksperymentuję z różnymi projektami. Czasem, żeby dostać jakąś próbkę muszę ustawić zapas na kilka dni. Niestety "przy okazji" z takiego np. PG zdąży wpaść i 50 wu, które później wywalam. Wiem, że należy nastawić "nie pobieraj", ale czasem zdarza się zapomnieć.

AiDec

Standardowo, w prawie wszystkich projektach, przerwanie zadania jest rownoznaczne z niepoprawnym przeliczeniem. A zatem obniza daily quota.



Bo jest paru kumpli :),
Bo jest parę w życiu dobrych chwil...


Moja wizytowka i sygnaturka

TJM

Dokładnie tak to działa, na dodatek w starszych wersjach serwera przerwanie podbijało error_rate hosta, czy nadal tak jest nie sprawdzałem. To drugie jest totalnie bez sensu, bo anulowanie zadań jest na pewno lepszym sposobem niż ich kiszenie aż przekisną w wypadku nadmiaru - z anulowanym zadaniem serwer radzi sobie doskonale wysyłając od razu resenda, kiszone wisi w bazie aż do timeouta, po czym również następuje resend, ale workunit jako taki ma wpisy w bazie ze 2 razy dłużej.
Tutaj jednak sytuacja jest jeszcze trochę inna, podczas procesu walidacji serwer może początkowo obniżyć daily quota za anulowanie zadań (pozostałość BOINCowego kodu validatora), ale i tak przywróci maksymalną wartość przy pierwszym poprawnym zwróconym wyniku, bo daemon który zajmuje się ustalaniem aktualnej wartości nresults_today i daily_quota ma po prostu w nosie takie drobiazgi, jak anulowanie zadań. Dla niego liczą się tylko poprawność/niepoprawność wyniku.

Rozważam jeszcze możliwość wprowadzenia bonusu dla 'reliable hostów' - komputery które w momencie odsyłania wyniku miałyby error_rate = 0, mogłyby dostawać jakiś dodatek do punktów za zadanie. Takie komputery są szczególnie cenne z punktu widzenia każdego projektu, bo trafiają do nich zadania które często nie będą miały więcej szans na przeliczenie. Przykładowo, w enigmie zadanie ma około 28 dni na powrót do serwera M4, to daje możliwość przekiszenia zadania dwa razy, ale trzeci resend zostanie wysłany ze skróconym deadline i jeśli nie wróci w czasie, serwer M4 takiego rezultatu nie przyjmie. Co prawda serwer nadal potrafi obsłużyć taki rezultat (czeka na inny workunit z serwera M4 z tymi samymi danymi, do których rezultat będzie pasował), jednak kosztem bardzo obciążających operacji na bazie danych.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

TJM

Poprawiłem dziś resztę drobnych bugów w backendzie i przy okazji znalazłem bug w BOINCu lub przynajmniej jego dokumentacji.
Domyślnie pole workunit.name to max 254 znaki tekstu. Założony jest indeks który automatycznie zabrania wstawienia dwóch workunitów o takiej samej nazwie.
Ale kto by przypuszczał, że nikt nie pomyślał wstawić tam do typu danych BINARY ? Bez tego dupa = dUPa = DUPA, więc nie da się wstawiać również workunitów o nazwach innych, pisanych z różną wielkością liter. Przez to serwer po prostu nie chciał mi wstawiać niektórych workunitów do tabeli, a ja się głowiłem czemu...


W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

TJM

Zbudowałem z ciekawości nowy set optymalizowanych aplikacji, w VS 2008. Są tylko dwie sensowne: SSE i SSE2.
Na razie szału nie ma, uzyskałem wyniki na poziomie zbliżonym do starych najlepszych aplikacji. Ale myślę, że zmieniając w opcjach co nieco da się jeszcze dorzucić jakiś bonus do prędkości, więc niewykluczone, że dałoby radę zbudować coś szybszego. Niestety nie używam VS na codzień, więc nie bardzo wiem od czego zacząć.
Orientuje się ktoś, czy jeśli ustawię inline functions -> any suitable, to nadal kompilator będzie brał pod uwagę funkcje oznaczone jako _inline_ ? GCC miał z tym poważne problemy, musiałem całe źródło przepisać, tak żeby w ogóle nie było tych funkcji.

EDIT: oraz fajnie by było, gdyby ktoś z AMD/Win32 przetestował jak się miewa prędkość, może dla AMD będzie na dzieńdobry lepiej niż standard z MinGW.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

sesef

Cytat: TJM w 16 Sierpień 2009, 18:48
Zbudowałem z ciekawości nowy set optymalizowanych aplikacji, w VS 2008. Są tylko dwie sensowne: SSE i SSE2.
Na razie szału nie ma, uzyskałem wyniki na poziomie zbliżonym do starych najlepszych aplikacji. Ale myślę, że zmieniając w opcjach co nieco da się jeszcze dorzucić jakiś bonus do prędkości, więc niewykluczone, że dałoby radę zbudować coś szybszego. Niestety nie używam VS na codzień, więc nie bardzo wiem od czego zacząć.
Orientuje się ktoś, czy jeśli ustawię inline functions -> any suitable, to nadal kompilator będzie brał pod uwagę funkcje oznaczone jako _inline_ ? GCC miał z tym poważne problemy, musiałem całe źródło przepisać, tak żeby w ogóle nie było tych funkcji.

EDIT: oraz fajnie by było, gdyby ktoś z AMD/Win32 przetestował jak się miewa prędkość, może dla AMD będzie na dzieńdobry lepiej niż standard z MinGW.

Kompilator z VS2008 nie jest zły, ale jak już przebudowałeś source tak, żeby działało pod VS2008 (kiedyś próbowałem, no ale jakieś linuxowe funkcje tam siedziały, więc dałem sobie spokój ) to zainteresuj się kompilatorem intela dla windowsa powinno dać dużo lepsze przyspieszenie niż sam vs.

Możesz podesłać przerobione source to może i ja bym się trochę pobawił?

TJM

Nie potrafię w ogóle podpiąć kompilatora Intela pod Visual Studio, kiedyś ostro z tym walczyłem ale miałem poważne problemy. Udało mi się jedynie pod Visual C++.
Źródło później gdzieś wrzucę, mam chwilowo jedynie jakieś niechlujne na którym dużo rzeczy testowałem, ale projekt i patch da się spokojnie nałożyć na domyślne.

Nie wiesz jak wygląda sytuacja z inline funkcjami w visualu ? Domyślnie nie wciąga nawet najprostszych funkcji jako inline (widzę to od razu po wielkości exeka), a z doświadczenia wiem, że daje to spory przyrost prędkości. Z kolei gdy zdeklaruję coś z inline, __inline lub __forceinline, kompilacja sypie się z błędami linkera.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

sesef

Cytat: TJM w 16 Sierpień 2009, 22:26Nie wiesz jak wygląda sytuacja z inline funkcjami w visualu ? Domyślnie nie wciąga nawet najprostszych funkcji jako inline (widzę to od razu po wielkości exeka), a z doświadczenia wiem, że daje to spory przyrost prędkości. Z kolei gdy zdeklaruję coś z inline, __inline lub __forceinline, kompilacja sypie się z błędami linkera.

inline jakoś nie chce działać na VS ten sam problem był podczas kompilacji milky nie chciał dodawać inline takich funkcji jak sin czy cos a z tego co potem mindc wykombinował na intelu to już wszystko ładnie poszło.

Cytat: TJM w 16 Sierpień 2009, 22:26
Nie potrafię w ogóle podpiąć kompilatora Intela pod Visual Studio, kiedyś ostro z tym walczyłem ale miałem poważne problemy. Udało mi się jedynie pod Visual C++.
Źródło później gdzieś wrzucę, mam chwilowo jedynie jakieś niechlujne na którym dużo rzeczy testowałem, ale projekt i patch da się spokojnie nałożyć na domyślne.

Korzystasz z darmowej wersji express? Kiedyś potrzebowałem na szybko kompilator x64 a na maszynie była tylko wersja express i niestety nie udało mi się zmusić kompilatora do działania. Na domowej maszynie mam wersje Team System i nie ma takich problemów.

TJM

No cóż, widocznie będę musiał ręcznie rozwinać źródło, jak dla gcc który też coś sapał. Wtedy niedziałanie inline samego kompilatora nie jest problemem.

Co do VS, to mam full wersję, ale mimo to miałem jakieś problemy. Niestety wyczerpałem 30-day triala na obu zainstalowanych systemach, więc póki co nawet nie potestuję czy da się coś jeszcze z tym zrobić.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

sesef

Cytat: TJM w 16 Sierpień 2009, 22:47Co do VS, to mam full wersję, ale mimo to miałem jakieś problemy. Niestety wyczerpałem 30-day triala na obu zainstalowanych systemach, więc póki co nawet nie potestuję czy da się coś jeszcze z tym zrobić.

Do testów możesz zainstalować wersje express ten sam kompilator tylko nie ma x64 jest jedynie x86 i trochę okrojony interfejs, ale z tego co pamiętam opcje kompilacji wszystkie te same.

Edit

Ahh te 30 dni to chodziło o intela, a nie o VS, co do samego intela tez ciekawa sprawa bo zainstalowałem u siebie triala ze strony intela i jakos na win7 ten trial się nie kończy :D

TJM

U mnie trial przywiesił się na ostatnich dniach, ale ostatecznie w końcu kompilator i tak się przyblokował.

Nie rozumiem jednej rzeczy kurcze.



double icscore(const int *stbrett, const int *ciphertext, int len)
{
 int f[26] = {0};
 int S0, S1, S2, S3;
 int c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16;
 int i;

 if (len < 2)
   return 0;

 for (i = 0; i < len-15; i += 16) {
   c1 = stbrett[ciphertext[i]];
   c1 = path_lookup[i][c1];
   c1 = stbrett[c1];

   c2 = stbrett[ciphertext[i+1]];
   c2 = path_lookup[i+1][c2];
   c2 = stbrett[c2];

   c3 = stbrett[ciphertext[i+2]];
   c3 = path_lookup[i+2][c3];
   c3 = stbrett[c3];

   c4 = stbrett[ciphertext[i+3]];
   c4 = path_lookup[i+3][c4];
   c4 = stbrett[c4];

   c5 = stbrett[ciphertext[i+4]];
   c5 = path_lookup[i+4][c5];
   c5 = stbrett[c5];

   c6 = stbrett[ciphertext[i+5]];
   c6 = path_lookup[i+5][c6];
   c6 = stbrett[c6];

   c7 = stbrett[ciphertext[i+6]];
   c7 = path_lookup[i+6][c7];
   c7 = stbrett[c7];

   c8 = stbrett[ciphertext[i+7]];
   c8 = path_lookup[i+7][c8];
   c8 = stbrett[c8];

   c9 = stbrett[ciphertext[i+8]];
   c9 = path_lookup[i+8][c9];
   c9 = stbrett[c9];

   c10 = stbrett[ciphertext[i+9]];
   c10 = path_lookup[i+9][c10];
   c10 = stbrett[c10];

   c11 = stbrett[ciphertext[i+10]];
   c11 = path_lookup[i+10][c11];
   c11 = stbrett[c11];

   c12 = stbrett[ciphertext[i+11]];
   c12 = path_lookup[i+11][c12];
   c12 = stbrett[c12];

   c13 = stbrett[ciphertext[i+12]];
   c13 = path_lookup[i+12][c13];
   c13 = stbrett[c13];

   c14 = stbrett[ciphertext[i+13]];
   c14 = path_lookup[i+13][c14];
   c14 = stbrett[c14];

   c15 = stbrett[ciphertext[i+14]];
   c15 = path_lookup[i+14][c15];
   c15 = stbrett[c15];

   c16 = stbrett[ciphertext[i+15]];
   c16 = path_lookup[i+15][c16];
   c16 = stbrett[c16];

   f[c1]++;
   f[c2]++;
   f[c3]++;
   f[c4]++;
   f[c5]++;
   f[c6]++;
   f[c7]++;
   f[c8]++;
   f[c9]++;
   f[c10]++;
   f[c11]++;
   f[c12]++;
   f[c13]++;
   f[c14]++;
   f[c15]++;
   f[c16]++;
 }
 for (; i < len-3; i += 4) {
   c1 = stbrett[ciphertext[i]];
   c1 = path_lookup[i][c1];
   c1 = stbrett[c1];

   c2 = stbrett[ciphertext[i+1]];
   c2 = path_lookup[i+1][c2];
   c2 = stbrett[c2];

   c3 = stbrett[ciphertext[i+2]];
   c3 = path_lookup[i+2][c3];
   c3 = stbrett[c3];

   c4 = stbrett[ciphertext[i+3]];
   c4 = path_lookup[i+3][c4];
   c4 = stbrett[c4];

   f[c1]++;
   f[c2]++;
   f[c3]++;
   f[c4]++;
 }
 for (; i < len; i++) {
   c1 = stbrett[ciphertext[i]];
   c1 = path_lookup[i][c1];
   c1 = stbrett[c1];
   f[c1]++;
 }


 S0 = S1 = S2 = S3 = 0;
 for (i = 0; i < 23; i += 4) {
   S0 += f[i]*(f[i]-1);
   S1 += f[i+1]*(f[i+1]-1);
   S2 += f[i+2]*(f[i+2]-1);
   S3 += f[i+3]*(f[i+3]-1);
 }
 S0 += f[24]*(f[24]-1);
 S1 += f[25]*(f[25]-1);

 //return (double)((S0+S1) + (S2+S3)) / (len*(len-1));
 fprintf(stderr, "i/c debug: %i  \n", S0+S1+S2+S3);
 return (double)((S0+S1) + (S2+S3));

}



To jest funkcja, gdzie myślałem o zmianie double na 64 bit integera, bo pamiętałem jeszcze z listy mailingowej M4 wzmianki o ogromnych liczbach jakie tu występują. A tymczasem:

Cytat: icscore
i/c debug: 442  
i/c debug: 454  
i/c debug: 448  
i/c debug: 474  
i/c debug: 438  
i/c debug: 440  
i/c debug: 488  
i/c debug: 506  
i/c debug: 430  
i/c debug: 450  
i/c debug: 426  
i/c debug: 492  
i/c debug: 488  
i/c debug: 476  
i/c debug: 470  
i/c debug: 442  
i/c debug: 408  
i/c debug: 488  
i/c debug: 496  
i/c debug: 462  
i/c debug: 460  
i/c debug: 472  
i/c debug: 476  
i/c debug: 476  
i/c debug: 460  
i/c debug: 462  
i/c debug: 472  
i/c debug: 456  
i/c debug: 464  
i/c debug: 446  
i/c debug: 440  
i/c debug: 464  
i/c debug: 456  
i/c debug: 464  
i/c debug: 440  
i/c debug: 446  
i/c debug: 436  
i/c debug: 424  
i/c debug: 488  
i/c debug: 462  
i/c debug: 436  
i/c debug: 456  
i/c debug: 484  
i/c debug: 472  
i/c debug: 544  
i/c debug: 514  
i/c debug: 516  
i/c debug: 524  
i/c debug: 542  
i/c debug: 556  
i/c debug: 538  
i/c debug: 512  
i/c debug: 524  
i/c debug: 522  
i/c debug: 516  
i/c debug: 520  
i/c debug: 542  
i/c debug: 530  
i/c debug: 532  
i/c debug: 534  
i/c debug: 532  
i/c debug: 510  
i/c debug: 496  
i/c debug: 516  
i/c debug: 480  
i/c debug: 476  
i/c debug: 532  
i/c debug: 510  
i/c debug: 532  
i/c debug: 534  
i/c debug: 558  
i/c debug: 600  
i/c debug: 532  
i/c debug: 538  
i/c debug: 570  
i/c debug: 544  
i/c debug: 596  
i/c debug: 548  
i/c debug: 530  
i/c debug: 574  
i/c debug: 564  
i/c debug: 540  
i/c debug: 536  
i/c debug: 528  
i/c debug: 516  
i/c debug: 534  
i/c debug: 510  
i/c debug: 546  
i/c debug: 592  
i/c debug: 564  
i/c debug: 520  
i/c debug: 508  
i/c debug: 482  
i/c debug: 470  
i/c debug: 570  
i/c debug: 538  
i/c debug: 510  
i/c debug: 546  
i/c debug: 516  
i/c debug: 534  
i/c debug: 516  
i/c debug: 540  
i/c debug: 584  
i/c debug: 590  
i/c debug: 550  
i/c debug: 546  
i/c debug: 496  
i/c debug: 510  
i/c debug: 504  
i/c debug: 490  
i/c debug: 550  
i/c debug: 546  
i/c debug: 584  
i/c debug: 590  
i/c debug: 482  
i/c debug: 470  
i/c debug: 520  
i/c debug: 508

ciekawe, gdzie tkwi haczyk...

Teoretycznie ciphertext może być o wiele dłuższy, ale według podręcznika operatora enigmy, nie wolno bylo przekroczyć chyba koło 300 znaków.


Zastanawiają mnie też porównania tego typu


                    if (ic-bestic > DBL_EPSILON) {
                      bestic = ic;
                      action = KZ_IZ;
                    }


Skoro po usunięciu dzielenia, które praktycznie nic nie wnosi (przecież i bez dzielenia lepszy score zawsze będzie lepszy, a gorszy będzie gorszy) liczba mieści się powiedzmy w  1000, to po co użyty typ double i jeszcze takie dziwne porównania  |-? DBL_EPSILON zdefiniowany jest jako 0.000000001.
Zastanawiam się, jakie to może mieć znaczenie dla logiki programu.
Możliwe, że dzielenie ma wnieść jakąś dodatkową zależność score od długości tekstu, ale skoro aplikacja cały czas pracuje na tekście jednej długości, to po co to  |-? Chyba spróbuję to pousuwać razem z tym DBL_EPSILONem i przetestować jak zachowa się aplikacja.
Nie wiem na ile bezpieczne są takie modyfikacje, bo aplikacja może działać poprawnie i zwracać poprawne wyniki, ale jakość hillclimba może spaść na łeb i cały soft nie będzie w stanie nic złamać.

W razie jakiejś pilniejszej sprawy - jestem często dostępny na kanale IRC B@P, na forum czasami zapominam zajrzeć lub nie mam czasu.

sesef

a jakbyś chciał wypisywać double dostajesz te same wyniki? Teoretycznie %i mogło coś obciąć, chociaż i tak liczby są za małe.

Może złe zadania podajesz, w innych może są to te ogromne liczby.