определить четность битового представления числа в MIPS

Есть ли какая-нибудь инструкция в MIPS, которая будет определять четность определенного битового представления? Я знаю, чтобы определить, имеет ли "число" четную или нечетную четность, нужно выполнить операцию XOR для отдельных битов двоичного представления вместе, но это кажется ресурсоемким для набора инструкций MIPS ... и мне нужно сделать это как можно быстрее.

Кроме того, число, с которым я работаю, представлено в Кодексе Грея ... просто чтобы добавить его туда. Так есть ли в MIPS какая-то псевдо-инструкция для определения четности «числа» или мне нужно делать это вручную?

Если нет инструкции MIPS, что кажется очень маловероятным, какие-либо советы, как это сделать вручную?

Спасибо, Христо

продолжение: я нашел оптимизацию, но моя реализация не работает.

unsigned int v; // 32-bit word
v ^= v >> 1;
v ^= v >> 2;
v = (v & 0x11111111U) * 0x11111111U;
return (v >> 28) & 1;

person Hristo    schedule 11.04.2010    source источник


Ответы (1)


Я не знаю ни одного варианта MIPS с инструкцией по четности, но есть хитрый трюк для вычисления четности быстрее, чем очевидный метод прохождения каждого из 32 битов по очереди. В C:

result = in ^ (in >> 16);
result ^= (result >> 8);
result ^= (result >> 4);
result ^= (result >> 2);
result ^= (result >> 1);
result &= 1;
  • После первого шага нижние 16 бит результата содержат биты четности N и N + 16 входа - по сути, 16 шагов вычисления четности были выполнены за один раз. Запись result{N} для обозначения "бит N из result":

    result{0}  =  in{0} ^ in{16}
    result{1}  =  in{1} ^ in{17}
    result{2}  =  in{2} ^ in{18}
    ...
    result{7}  =  in{7} ^ in{23}
    result{8}  =  in{8} ^ in{24}
    ...
    result{15} = in{15} ^ in{31}
    

    (а оставшиеся 16 старших бит result теперь можно игнорировать; они не служат никакой полезной цели в оставшейся части вычислений).

  • После второго шага нижние 8 бит result содержат биты четности N, N + 8, N + 16, N + 24 исходного ввода:

    result{0} = result{0} ^ result{8}  =  in{0} ^  in{8} ^ in{16} ^ in{24}
    result{1} = result{1} ^ result{9}  =  in{1} ^  in{9} ^ in{17} ^ in{25}
    ...
    result{7} = result{7} ^ result{15} =  in{7} ^ in{15} ^ in{23} ^ in{31}
    

    (и, опять же, оставшиеся биты с этого момента можно игнорировать).

  • ... и так далее, пока четность всех битов исходного ввода не окажется в нижнем бите result:

    result{0} = in{0} ^ in{1} ^ in{2} ^ ... ^ in{30} ^ in{31}
    

Это легко перевести прямо на сборку MIPS; это 11 инструкций:

# input in $a0, output in $v0, $t0 corrupted
srl $t0, $a0, 16
xor $v0, $a0, $t0
srl $t0, $v0, 8
xor $v0, $v0, $t0
srl $t0, $v0, 4
xor $v0, $v0, $t0
srl $t0, $v0, 2
xor $v0, $v0, $t0
srl $t0, $v0, 1
xor $v0, $v0, $t0
and $v0, $v0, 1

Возможным улучшением может быть использование таблицы поиска. Например, после первых двух шагов мы имеем:

    result{0} =  in{0} ^  in{8} ^ in{16} ^ in{24}
    result{1} =  in{1} ^  in{9} ^ in{17} ^ in{25}
    ...
    result{7} =  in{7} ^ in{15} ^ in{23} ^ in{31}

так что на этом этапе мы могли бы использовать 256-байтовую таблицу поиска. В C:

result = in ^ (in >> 16);
result ^= (result >> 8);
result = lookup_table[result & 0xff];

где lookup_table[n] было предварительно вычислено, например:

for (i = 0; i < 256; i++) {
    n = i ^ (i >> 4);
    n ^= (n >> 2);
    n ^= (n >> 1);
    lookup_table[i] = n & 1;
}

Это 7 инструкций MIPS, не считая загрузки базового адреса таблицы поиска в регистр:

# input in $a0, lookup table address in $a1, output in $v0, $t0 corrupted
srl  $t0, $a0, 16
xor  $v0, $a0, $t0
srl  $t0, $v0, 8
xor  $v0, $v0, $t0
andi $v0, $v0, 0xff
addu $t0, $a1, $v0
lbu  $v0, 0($t0)

Однако это 7 инструкций, которые включают доступ к памяти, по сравнению с 11 инструкциями, которые являются чисто регистровыми операциями; это может быть или не быть быстрее. (Такого рода микрооптимизация всегда требует профилирования!)

person Matthew Slattery    schedule 11.04.2010
comment
Спасибо за ответ. Это то, что у меня сейчас есть ... но я пытаюсь оптимизировать код для меньшего количества инструкций, потому что этот набор инструкций будет вызываться много раз, и это снижает производительность. Есть идеи по оптимизации? - person Hristo; 11.04.2010
comment
После второго xor вся полезная информация находится в нижних 8 битах; окончательный ответ - это просто функция этих битов, так что вы можете использовать их в качестве индекса в 256-байтовой таблице поиска в этот момент. Будет ли это работать быстрее или нет, зависит от скорости доступа к памяти, кеширования и т. Д. - вам нужно попробовать это и профилировать ... - person Matthew Slattery; 11.04.2010
comment
Что вы имеете в виду, говоря, что вся полезная информация находится в нижних 8 битах? Итак, вы предлагаете shift 16, xor, shift 8, xor, а затем самые правые 8 бит являются важными? - person Hristo; 11.04.2010
comment
В порядке. Большое спасибо! Я реализовал это, и это не работает, но я уверен, что у меня что-то не так, чего я не вижу. - person Hristo; 11.04.2010
comment
@Hristo: ой, нет, это моя вина за то, что я испортил инициализацию таблицы поиска. Я исправил это сейчас. Извини за это. - person Matthew Slattery; 11.04.2010
comment
Спасибо, что дал мне знать. На самом деле я не использовал вашу справочную таблицу, однако инструкции 7 MIPS работают хорошо. Теперь он у меня работает, и это довольно быстро :) Большое спасибо! - person Hristo; 12.04.2010