логический сдвиг вправо в numba

Следующий код

@jit(uint32(uint32))
def foo(x): 
    return (x >> 6)

print(hex(foo(0xffffffff)))

выходы

0xffffffff

потому что numba использует арифметический сдвиг вправо, несмотря на то, что операнд определен как беззнаковый.

Есть ли способ передать это, используя логический сдвиг?

На самом деле, из ответа ДжошаАделя ниже я узнал обходной путь - использование внутренней 64-битной переменной, для которой логические и арифметические сдвиги не будут отличаться. Нравится:

@jit(uint32(uint32), locals = {'t': uint64})
def foo1(x):
    t = x 
    return t << 8

@jit(uint32(uint32), locals = {'t': uint64})
def foo2(x):
    t = x 
    return t >> 8

print(hex(foo1(0xffffffff)))
print(hex(foo2(0xffffffff)))

который печатает

0xffffff00
0xffffff

Но порядочный компилятор должен понимать, что >>, примененное к числу unsigned, должно привести к логическому сдвигу.


person uk-ny    schedule 20.07.2016    source источник
comment
Если ответ JoshAdel не приведет вас к решению, вы можете вместо этого попробовать x / (1 << 6) и посмотреть, оптимизирует ли дрожание его до логического сдвига вправо.   -  person Andrew Morton    schedule 20.07.2016
comment
Пробовали. Дивизия остается в сборе. Очень плохо.   -  person uk-ny    schedule 20.07.2016
comment
Можете ли вы привести (1 << 6) к беззнаковому типу (чтобы обе стороны деления были беззнаковыми) и проверить получившуюся сборку? Я предполагаю, что есть шанс, что если он увидит uint / uint, он оптимизирует его, а не uint / int.   -  person Andrew Morton    schedule 20.07.2016


Ответы (1)


Я получаю тот же ответ от чистых версий python и numba с использованием Numba 0.27:

import numba as nb

def foo(x): 
    return (x >> 6)

foo_nb = nb.jit()(foo)

print(hex(foo(0xffffffff)))
print(hex(foo_nb(0xffffffff)))

приводит к:

0x3ffffff
0x3ffffff

Следующее также дает тот же результат (чтобы убедиться, что мы не возвращаемся к объектному режиму и фактически используем полный jit):

foo_nb2 = nb.jit('uint(uint)', nopython=True)(foo)
print(hex(foo_nb2(0xffffffff)))

# prints 0x3ffffff

Какую версию Numba вы используете?

person JoshAdel    schedule 20.07.2016
comment
foo_nb.inspect_types() показывает, что на самом деле numba использует int64 и арифметические сдвиги. Это не решает проблему, а только скрывает ее до тех пор, пока левые сдвиги не подтолкнут число так, чтобы бит MS 64-битного числа стал 1. Тогда это даст неожиданные результаты. - person uk-ny; 20.07.2016
comment
Хм... Глядя на foo_nb2.inspect_types(), похоже, что он использует unint64 в качестве типа ввода, переключается на int64, а затем возвращается к uint64 в конце. Я бы поднял вопрос в системе отслеживания проблем Numba, если вы считаете, что код переведен неправильно. Обычно они очень отзывчивы. - person JoshAdel; 20.07.2016
comment
Может ли это быть регрессом к ошибкам оператора побитового сдвига № 191? - person Andrew Morton; 20.07.2016