Лучший вариант для расчета логического уравнения? - PullRequest
0 голосов
/ 20 марта 2012

Итак, я делаю эмулятор Hack CPU, и мне было интересно, как лучше рассчитать результат. Будет ли объединение вычислений в одну нечитаемую строку более эффективным, чем вычисление результата по одному шагу за раз? Оптимизирует ли это компилятор так, что оба варианта хороши? В основном, какой из них более эффективен -

это:

    word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no)
    {
        x = zx ? 0 : x;
        y = zy ? 0 : y;

        x = nx ? ~x : x;
        y = ny ? ~y : y;

        word result = f ? x + y : x & y;

        return no ? ~result : result;    
    }

или это:

    word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no)
    {
        return no ? ~(f ? ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) + (ny ? ~(zy ? 0 : y) : (zy ? 0 : y))) : ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) & (ny ? ~(zy ? 0 : y) : (zy ? 0 : y)))) : (f ? ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) + (ny ? ~(zy ? 0 : y) : (zy ? 0 : y))) : ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) & (ny ? ~(zy ? 0 : y) : (zy ? 0 : y))));
    }

Ответы [ 3 ]

1 голос
/ 21 марта 2012

Логические изменения будут иметь большее влияние на производительность кода, чем пробелы / хранилище временных значений.

Например, некоторые машины не имеют предсказания ветвлений (например, SPU для PS3), и в этом случае ваш код будет значительно быстрее, если заменить ветки математическими операциями

word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no)
{
    x = (zx == 0) * x; // [0 or 1] * x;
    y = (zy == 0) * y;

    x -= (nx != 0) * 2 * x;
    y -= (ny != 0) * 2 * x;

    word result = (f != 0) * (x + y) + (f == 0) * (x & y);

    return (no != 0) * ~result + (no == 0) * result;    
}
1 голос
/ 20 марта 2012

Хороший современный компилятор, скорее всего, сгенерирует идентичный код для обоих.

0 голосов
/ 21 марта 2012

Используя этот цикл, я на самом деле показываю верхнюю версию быстрее:

int n = 0; //optimization busting counter
clock_t start = clock();
    for( word x=0; x<1000; ++x ) {
    for( word y=0; y<1000; ++y ) {
        for( int b = 0; b < 64; ++b ) {
            n += HackALU(x,y,b&0x1,b&0x2,b&0x4,b&0x8,b&0x10,b&0x20);
}   }   }
clock_t end = clock();
printf("finished, elapsed ticks = %d, n = %d\n", end - start, n);

Совершенно очевидно, что в верхней версии было бы меньше инструкций, если бы оптимизатор не был действительно хорош ... Я думаю, что для его ускорения потребовалось бы уменьшить количество ветвей или убедиться, что они точно предсказаны.

...