Компилирует ли Cython статические ключи для их хеш-значений?

1

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

Например:

for d in large_list_of_dicts:
    for d2 in d['trees']:
        v = d2['leaves']

Хитует ли Cython эти статические строковые ключи для хэш-значений (только один раз) и повторно использует эти хэши? Если да, может ли это значительно улучшить производительность таких циклов?

  • 4
    Я не знаком с Cython, но даже в обычном Python для заданного строкового объекта будет вычислен хэш не более одного раза - он кэшируется в объекте. Я не могу представить, что Cython отбросил бы такую базовую оптимизацию.
  • 0
    @jasonharper Спасибо, я этого не осознавал. Похоже, что использование Cython здесь мало что даст.
Теги:
optimization
dictionary
cython

1 ответ

1
Лучший ответ

Cython не будет выполнять здесь никакой магии: он просто делегирует вызовы PyDict_GetItemWithError - в основном то же самое, что будет делать интерпретатор Python (но, вероятно, немного быстрее).

Однако unicode-объект (я предполагаю, что мы говорим о Python3-строках) кэширует свое хеш-значение (в PyUnicodeObject.hash -member), поэтому его необходимо вычислять только один раз - что имеет смысл, потому что Unicode-объект является неизменным, это означает, что хэш не может измениться.

Вот код CPython, ответственный за вычисление/кэширование хеша:

#define _PyUnicode_HASH(op)                             \
(((PyASCIIObject *)(op))->hash)
...

static Py_hash_t
unicode_hash(PyObject *self)
{
    ...
    // if hash already calculated, return cached value
    if (_PyUnicode_HASH(self) != -1)
        return _PyUnicode_HASH(self);
    ...
    // else caclculate hash, cache value, return it
    x = _Py_HashBytes(PyUnicode_DATA(self),
                      PyUnicode_GET_LENGTH(self) * PyUnicode_KIND(self));
    _PyUnicode_HASH(self) = x;
    return x;
}

Итак, как вы можете видеть, Cython не нужно избегать пересчета хеша - эта оптимизация уже выполнена CPython.

Используя здесь Cython, можно выиграть до 10-30%, потому что это исключит интерпретатор для этой части кода (см., Например, этот SO-пост) - не очень много, но лучше, чем ничего.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню