расширение Python c для стандартного отклонения

1

Я пишу расширение c, чтобы вычислить его стандартное отклонение. Производительность важна, поскольку она будет выполняться на больших наборах данных. Мне сложно понять, как получить значение pyobject, как только я получу элемент из списка. Это мой первый раз, когда я пишу c-расширение для python, и любая помощь приветствуется. По-видимому, я не знаю, как правильно использовать кнопку примера кода: (

Это то, что у меня есть до сих пор:

    #include <Python.h>
static PyObject*
func(PyObject *self, PyObject *args)
{
  PyObject *list, *item;
  Py_ssize_t i, len;
  if (!PyArg_UnpackTuple(args, "func", 1, 1, &list)){
    return NULL;
  }
  printf("hello world\n");
  Py_INCREF(list);
  len = PyList_GET_SIZE(list);
  for (i=0;i<len;i++){
    item = PyList_GET_ITEM(list, i);
    PyObject_Print(item,stdout,0);
  }
  return list;
}

static char func_doc[] = "This function calculates standard deviation.";

static PyMethodDef std_methods[] = {
  {"func", func, METH_VARARGS, func_doc},
  {NULL, NULL}
};

PyMODINIT_FUNC
initstd(void)
{
  Py_InitModule3("std", std_methods, "This is a sample docstring.");
}
Теги:
performance
standard-deviation

6 ответов

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

Вы можете изобретать колесо. Для Python существует несколько научных вычислительных библиотек, таких как SciPy и Numpy, которые в основном представляют собой оболочки вокруг библиотек C, которые реализуют такие функции, как стандартное отклонение.

  • 0
    В настоящее время я использую NumPy для расчета, но сначала необходимо преобразовать список в NUMPY, и я бы хотел избежать этого, поскольку списки велики, а весь набор данных составляет сотни мегабайт. Хотя я не эксперт, и, возможно, это не слишком дорого для производительности вычислений, но я бы хотел увидеть разницу в скорости с помощью одного из профилировщиков Python.
  • 0
    Преобразование в массив Numpy может оказаться не таким уж сложным делом, как вы себе представляете. Если вы загружаете свои данные из файла или базы данных, вы уже делаете значительные накладные расходы, чтобы загрузить их как обычный список Python. Если вы загрузите данные непосредственно в массив Numpy для начала, вы устраните эти издержки. Даже если вам нужно «преобразовать» из обычного списка в массив, вы можете позже сохранить свой массив Numpy для быстрой загрузки. docs.scipy.org/doc/numpy/reference/generated/numpy.load.html
1

Как только у вас есть item, вы можете получить его значение с плавающей точкой PyNumber_Float:

PyObject* floatitem = PyNumber_Float(item);

Теперь вам нужно проверить и выйти с ошибкой (if(!floatitem) return 0 - или goto в место, где вы уменьшаете все, что у вас может быть увеличено в предыдущей части кода, например, в вашем случае list). Если ошибка отсутствует, PyFloat_AsDouble дает требуемое значение double для использования в остальной части вашего C-кодированного цикла:

double ditem = PyFloat_AsDouble(floatitem);

после чего вы можете уменьшить floatitem и пойти своим весельем. Не беспокойтесь о чрезмерных затратах на конвертацию в PyNumber_Float - их не будет, если вы сначала передадите список поплавков;-). Если вы все еще беспокоитесь (скорее всего, допустите ошибку, если кто-то пропустит неплатеж, требующий преобразования), вы можете использовать PyFloat_Check, если вы настаиваете (но я бы предложил по крайней мере специальные элементы int и long если вы не хотите по-настоящему недоумевать и недовольных пользователей;-). В аналогичном ключе я также настоятельно рекомендую изучать и использовать PySequence_Fast и друзей, а не поразительных пользователей, специально требуя списков, а не другие типы последовательностей! -).

1

Считаете ли вы использование cython, чтобы написать расширение. Это идеально подходит для этого типа вещей

1

Просто упомянем, что есть почти наверняка лучший способ, чем писать расширение C.

Первый вариант - использовать NumPy. В комментарии, который вы указали на другой ответ, упоминается, что преобразовать список в массив очень дорого. Это может быть правдой, если расчет стандартного отклонения - это единственный бит, который вы делаете с данными, которые маловероятны.

Запрет на это, я бы пошел на Cython. Здесь - сравнение Cython и NumPy. В этом случае Cython в этом случае превосходит NumPy, но, что более важно, код, реализованный для csum, может быть тривиально изменен для вычисления стандартного отклонения.

0

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

0

Этот метод будет ограничен количеством элементов в списке.

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

Ещё вопросы

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