Wpis z mikrobloga

Mirki #programisci znacie szybszą metodę na czytanie intów oddzielonych spacjami w naszym ulubionym C niż to poniżej???

inline void fastReadint(int *x) {
register int c = getchar_unlocked();
*x = 0;

for(; ((c<48 || c>57) && c != ' '); c = getcharunlocked());

for(; c>47 && c<58 && c != ' ' ; c = getchar
unlocked()) {
*x = (*x<<1) + (*x<<3) + c - 48;
}
}_

#programowanie #c #informatyka
  • 3
  • Odpowiedz
1. Czemu zwracasz przez pointer? Możesz tym zrobić krzywdę optymalizatorowi.
2. inline i register nie są przypadkiem ignorowane przez praktycznie wszystkie kompilatory?
3. (x<<1) + (x<<3) wygląda pro, ale clang to optymalizuje do zwykłego x*10 http://goo.gl/eR0vNV

Also: c < '0' || c > '9' wygląda imho czytelniej niż c < 48 || c > 57

Optymalizowanie tego będzie prawdopodobnie sztuką dla sztuki, bo 99.9% czasu będzie spędzone wewnątrz wywołania getchar.
  • Odpowiedz
@Rett: po zastosowaniu się czas wykonania wzrósł z 0.35 s na 0.5 s (na wejściu dostaję duża ilość int'ów, np 10^9 liczb dodatnich).

O dziwo gcc 4.3.2 na linuksie nie ignoruje inline ani register. Po wrzuceniu zmiennej do rejestru procesora czas dostępu się skraca(testowałem) - różnica 0.1 sekundy przy dużym wejściu.

Na gcc przesunięcia bitowe działają szybciej niż zwykłe mnożenie, też sprawdzone - różnica
  • Odpowiedz
reszta operacji nie przekracza setnej sekundy.


@kleszczydron9000: Przesunięcie bitowe to akurat jedna operacja maszyny, co ciekawe ARM'y (nie wiem jak '86) dostarczają operację shift and multiply i różne ich kombinacje i to zajmuje 2 +/-1 takty zegara na operacje. Więc szukanie tu oszczędności jest mocno na siłę.
Skoro na gcc przesunięcia działają szybciej niż mnożenie na typie int wiedz, że masz stary kompilator. Tu różnice są wyraźne na maszynach typu AVR8.
Zwracanie pojedynczej wartości przez wskaźnik wiąże się z koniecznością pobrania wartości wskaźnika, ustawienia go na odpowiednią lokalizację, pewnie po dwie operacje load i store. Zwracanie przez wartość to raptem odłożenie i zdjęcie jej ze stosu. No i *x = 0 to dodatkowy narzut.
Dodatkowa pętla do kolejne
  • Odpowiedz