Отложенное выполнение в Python для больших данных - PullRequest
1 голос
/ 06 января 2010

Я пытаюсь подумать о том, как Python API может выглядеть для больших хранилищ данных, таких как Cassandra. R, Matlab и NumPy, как правило, используют формулировку «все является матрицей» и выполняют каждую операцию отдельно. Эта модель доказала свою эффективность для данных, которые могут поместиться в памяти. Однако одно из преимуществ SAS для больших данных заключается в том, что он выполняет строку за строкой, выполняя все вычисления строки перед переходом к следующей. Для такого хранилища данных, как Cassandra, эта модель кажется огромной победой - мы только один раз перебираем данные.

В Python подход SAS может выглядеть примерно так:

with load('datastore') as data:
  for row in rows(data):
    row.logincome = row.log(income)
    row.rich = "Rich" if row.income > 100000 else "Poor"

Это (тоже?) Явно, но преимущество в том, что цикл выполняется только один раз. Для небольших наборов данных производительность будет очень низкой по сравнению с NumPy, поскольку функции не векторизованы с использованием скомпилированного кода. В R / Numpy мы бы получили гораздо более краткую и скомпилированную информацию:

data.logincome = log(data.income)
data.rich = ifelse(data.income > 100000, "Rich", Poor")

Это будет выполнено очень быстро, потому что log и ifelse являются скомпилированными функциями, которые работают с векторами. Недостатком, однако, является то, что мы сделаем цикл дважды. Для небольших наборов данных это не имеет значения, но для хранилища данных с поддержкой Cassandra я не вижу, как работает этот подход.

Вопрос: есть ли способ сохранить второй API (например, R / Numpy / Matlab), но задержать вычисления. Возможно, вызывая функцию синхронизации (данных) в конце?

Альтернативные идеи? Было бы неплохо сохранить синтаксис типа NumPy, поскольку пользователи будут использовать NumPy для небольших операций и будут интуитивно понимать, как это работает.

Ответы [ 2 ]

2 голосов
/ 06 января 2010

Я ничего не знаю о Cassandra / NumPy, но если вы адаптируете свой второй подход (используя NumPy) для обработки данных в порциях разумного размера, вы можете извлечь выгоду из кэша ЦП и / или файловой системы и, следовательно, предотвратить любые замедление, вызванное повторным циклом данных, без потери преимущества использования оптимизированных функций обработки.

1 голос
/ 08 января 2010

У меня нет идеального ответа, просто грубая идея, но, возможно, оно того стоит. Он сосредоточен вокруг генераторов Python, в некотором роде как сочетание стиля производитель-потребитель.

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

for row in rows(data):
    # do stuff with row

Теперь передайте строку (произвольному количеству) потребителей, которые - не задушите - генераторы снова. Но вы бы использовали send метод генератора. В качестве примера для такого потребителя приведем набросок riches:

def riches():
    rich_data = []
    while True:
        row = (yield)
        if row == None: break
        rich_data.append("Rich" if row.income > 100000 else "Poor")
    yield rich_data

Первый выход (выражение) - просто залить отдельные строки в riches. Это делает свое дело, здесь строит массив результатов. После цикла while второй yield (оператор) используется для фактического предоставления данных результата вызывающей стороне.

Возвращаясь к циклу вызова, это может выглядеть примерно так:

richConsumer = riches()
richConsumer.next()  # advance to first yield
for row in rows(data):
    richConsumer.send(row)
    # other consumers.send(row) here
richConsumer.send(None)  # make consumer exit its inner loop
data.rich = richConsumer.next() # collect result data

Я не тестировал этот код, но я так думаю об этом. Он не имеет приятного компактного синтаксиса функций, основанных на векторах. Но это делает основной цикл очень простым и заключает в себе всю обработку в отдельных потребителях. Дополнительные потребители могут быть приятно сложены друг за другом. И API может быть еще более отшлифован, если поместить код управления генератором позади, например. границы объекта. НТН

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...