Составление обратных вызовов нативного / C кода в Python - PullRequest
0 голосов
/ 29 ноября 2018

Я интенсивно использую библиотеки числового анализа в Python, такие как подпрограммы оптимизации и интеграции Scipy, и многие из этих подпрограмм принимают обратный вызов, который оценивает какую-то целевую функцию в качестве основного аргумента.Из соображений производительности я часто реализую эти обратные вызовы в собственном коде (обычно с использованием Cython или Numba, которые генерируют код C, который компилируется, связывается и затем инкапсулируется в объекте Python).Многие подпрограммы Scipy теперь принимают экземпляр LowLevelCallable , который представляет собой такой объект, который содержит указатель на функцию C и информацию о ее сигнатуре.Если сама подпрограмма реализована на C или Cython, это может значительно сократить накладные расходы, полностью обходя интерпретатор Python.

То, что я пытаюсь выяснить, лучший способ сделать это - создать функции Python, которые принимают эти типынативные объекты обратного вызова, преобразовать их некоторым образом и вернуть другой собственный обратный вызов.Примером может служить функция, которая принимает обратный вызов, который прогнозирует y с учетом x вместе с массивом наблюдаемых значений y, и возвращает другой обратный вызов, который вычисляет ошибку в прогнозах по сравнению с наблюдениями.Затем результат может быть передан в scipy.optimize.minimize().

Реализация для обычных функций Python будет выглядеть примерно так:

import numpy as np

def make_error_callback(f, y_obs):
    def g(x):
        y = f(x)
        return np.sum((y - y_obs) ** 2)

    return g

Цель состоит в том, чтобы, если f было нативнымобратный вызов, который может быть оценен без вызова интерпретатора Python, тогда g также должно быть.make_error_callback, вероятно, должно быть реализовано в Cython или что-то подобное (в худшем случае фактический C с использованием Python C API).Фактические типы Python f и g будут представлять собой нечто, инкапсулирующее указатель на функцию C, например scipy.LowLevelCallable.

...