Przypisywać wartość warunkowo czy bezwarunkowo?

0

Jest taki kod:

typedef unsigned long N;

// Tutaj wcześniejsza część kodu.

N k_0 = E_asm_I_bsr( num_0->digits[ e_0 ] );
if( n_0 )
{   N k = E_asm_I_bsr( n_0 );
    n_0 <<= k_1 - k;
    n_0 |= num_0->digits[ e_0 ] >> ( sizeof(N) * 8 - ( k_1 - k ));
    if( n_0 < n_1 )
    {   j = 1;
        n_0 <<= j;
        n_0 |= num_0->digits[ e_0 ] >> ( sizeof(N) * 8 - j );
    }else
        j = 0;
    n_0 -= n_1;
    if( n_0 & ( (N)~0 << j ))
    {   if( !num_mod->digits_n )
        {   if( !E_mem_Q_blk_I_prepend( &num_mod->digits, 1 ))
            {   E_math_bignum_W( num_mod );
                return ~0;
            }
            num_mod->digits_n++;
            num_mod->digits[0] = 0;
        }
        num_mod->digits[0] |= n_0 >> j;
    }
    if(j)
    {   if( n_0 & j )
        {   if( k_0 != sizeof(N) * 8 - j )
                k_0 = sizeof(N) * 8 - j;
            num_0->digits[ e_0 ] |= (N)1 << k_0;
        }else if( ~k_0 ) // Ma być ten warunek czy nie?
            num_0->digits[ e_0 ] &= ((N)1 << ( sizeof(N) * 8 - j )) - 1;
    }
}
if( !~k_0 )
{   n_0 = 0;
    div = 0;
    goto Cont;
}

// Tutaj dalsza część kodu.

Cont:

Funkcja E_asm_I_bsr oblicza pozycję najbardziej znaczącego ustawionego bitu w liczbie. Oblicza za pomocą instrukcji BSR asemblera maszyny x86, jednak z tą różnicą, że jeśli nie ma ustawionego żadnego bitu, to wynik jest zdefiniowany i wynosi ~0UL czyli -1UL.

W linii 5. obliczam k_0 dla wartości num_0->digits[ e_0 ] z tablicy.
W linii 34. maskuję tę wartość num_0->digits[ e_0 ] do jej mniej znaczącego fragmentu.
Ale w linii 33. jest warunek: jeśli k_0 wynosi ~0UL czyli num_0->digits[ e_0 ] wynosi 0, to nie maskuj tej wartości num_0->digits[ e_0 ], ponieważ i tak jest już zerem, więc nie ma co maskować.

Teoretycznie kompilator wygeneruje dla tego warunku z linii 33. skok warunkowy po sprawdzeniu, czy k_0 jest równe ~0UL.

Możliwe są dwa przypadki:

  1. warunek z linii 33. jest
    Wtedy nie zostaną wykonane instrukcje odczytu i przypisania do pamięci, które mogłyby być kosztowne. Ale zawsze musi być wykonany skok warunkowy ponad tymi instrukcjami.
  2. warunku z linii 33. nie ma
    Wtedy nie potrzeba wykonywać być może kosztownego skoku warunkowego, ale zawsze konieczny jest odczyt i zapis do pamięci.

To jest fragment funkcji usługowej i nie wiem, w jakich przypadkach wartość num_0->digits[ e_0 ] będzie zerem lub nie.

3

Nie bardzo wiem, o co pytasz… Jakie są Twoje kryteria decyzyjne?

Wydajność? To przetestuj, będziesz wiedział z dalece większą pewnością, niż przez statyczną analizę kodu.

Czytelność? Powiedziałbym, że właściwie taka sama…

0
Althorion napisał(a):

Wydajność? To przetestuj, będziesz wiedział z dalece większą pewnością, niż przez statyczną analizę kodu.

Słuszna uwaga, zrobię to, gdy tylko napiszę funkcję wprowadzania danych, ponieważ trzeba by przetestować dla dużej ilości zer i nie zer.
Natomiast poniżej znajduje się to, co wygenerował dla tego bloku kompilator (z optymalizacją) dla warunku umieszczonego w kodzie.

   104a9:       80 7c 24 48 00          cmpb   $0x0,0x48(%rsp)
   104ae:       4c 89 7c 24 28          mov    %r15,0x28(%rsp)
   104b3:       75 4c                   jne    10501
   104b5:       41 f6 c7 01             test   $0x1,%r15b
   104b9:       75 1f                   jne    104da
   104bb:       48 83 7c 24 18 ff       cmpq   $0xffffffffffffffff,0x18(%rsp)
   104c1:       74 35                   je     104f8
   104c3:       49 8b 06                mov    (%r14),%rax
   104c6:       48 b9 00 00 00 00 00    movabs $0x8000000000000000,%rcx
   104cd:       00 00 80 
   104d0:       48 ff c9                dec    %rcx
   104d3:       48 21 4c f8 f8          and    %rcx,-0x8(%rax,%rdi,8)
   104d8:       eb 27                   jmp    10501
   104da:       49 8b 06                mov    (%r14),%rax
   104dd:       48 b9 00 00 00 00 00    movabs $0x8000000000000000,%rcx
   104e4:       00 00 80 
   104e7:       48 09 4c f8 f8          or     %rcx,-0x8(%rax,%rdi,8)
   104ec:       b8 3f 00 00 00          mov    $0x3f,%eax
   104f1:       48 89 44 24 18          mov    %rax,0x18(%rsp)
   104f6:       eb 09                   jmp    10501
   104f8:       48 c7 44 24 18 ff ff    movq   $0xffffffffffffffff,0x18(%rsp)
   104ff:       ff ff 

Linie od 6. do 12. to jest właśnie to przypisanie. Wydaje się, że skok warunkowy zajmie mniej cykli procesora.

A to poniżej dla warunku usuniętego z kodu.

   104bd:       80 7c 24 48 00          cmpb   $0x0,0x48(%rsp)
   104c2:       75 31                   jne    104f5
   104c4:       49 8b 06                mov    (%r14),%rax
   104c7:       48 b9 00 00 00 00 00    movabs $0x8000000000000000,%rcx
   104ce:       00 00 80 
   104d1:       48 ff c9                dec    %rcx
   104d4:       48 23 4c f8 f8          and    -0x8(%rax,%rdi,8),%rcx
   104d9:       4c 89 fa                mov    %r15,%rdx
   104dc:       48 c1 e2 3f             shl    $0x3f,%rdx
   104e0:       48 09 ca                or     %rcx,%rdx
   104e3:       41 f6 c7 01             test   $0x1,%r15b
   104e7:       b9 3f 00 00 00          mov    $0x3f,%ecx
   104ec:       4c 0f 45 e1             cmovne %rcx,%r12
   104f0:       48 89 54 f8 f8          mov    %rdx,-0x8(%rax,%rdi,8)
   104f5:       4c 89 7c 24 28          mov    %r15,0x28(%rsp)

Linie 3. do 7. to jest właśnie to przypisanie. Ale w tym przypadku kompilator wyeliminował sprawdzenie na początku, czy n0 & j jest różne od zera, i oblicza zawsze, a warunkowo tylko przypisuje wartość. Czy to jest szybsze niż ten wcześniejszy skok warunkowy...?

6

To pytanie pachnie jak mikrooptymalizacją, czyli założenie, że jakieś magiczne wyrażenie w kodzie, zmieni znacząco wydajność programu.

Problem polega na tym, że ten kod jest nieczytelny niezrozumiały i nie wiadomo co ma robić. Do tego jeszcze to goto.
Efekt jest taki, że nie ma możliwości by odpowiedzieć na pytanie: // Ma być ten warunek czy nie?. Udzielenie pomomocy w tym pytaniu jest bardzo utrudnione.

2

Ale w czym problem, bo nie widzę pytania?

0
overcq napisał(a):

Jest taki kod:

Często zachowuję resztki szacunku za to, ze goście nie przypisują sobie autorstwa kodu

1 użytkowników online, w tym zalogowanych: 0, gości: 1