Cython - самый быстрый способ передать числа с плавающей запятой для высокочастотных контуров управления - PullRequest
1 голос
/ 17 июня 2020

У меня есть функция (fun c) в классе c ++, и я хочу вызвать ее со стороны python, чтобы вызвать следующую последовательность с минимально возможной задержкой :

1_ на стороне python: fun c (np.array ([1,2,3,4,5]) или fun c ([1,2,3,4,5]) или 2D-массив и любое другое предложение, которое может быть у вас для более низкой задержки.

2_ на стороне c ++: у меня есть заполнитель типа franka :: RobotState robot_state_ , и я хочу скопировать часть вышеперечисленного массив внутри него. что-то, что я могу сделать, например:

for (int i = 0; i < 7; ++i) {
        robot_state_.q     [i] = array_that_came_from_python_side  [i];
        robot_state_.dq    [i] = array_that_came_from_python_side  [i+7];
        robot_state_.tau_J [i] = array_that_came_from_python_side  [i+14];
    }

3_Тогда следующие строки, которые я уже написал, обновят другой заполнитель типа franka :: Torques _eff_cmd , который я хотите вернуться на сторону python и представьте, что вы делаете это следующим образом:

for (int i = 0; i < 7; ++i) {
    array_to_return[i] = _eff_cmd[i]
    }
    return array_to_return // to be sent to the python side

где array_to_return может быть возвращен на стороне python с любым типом, таким как numpy массив или список или любое другое предложение, такое как ввод. а затем я повторю эту последовательность на стороне python с высокой частотой y, поскольку в основном речь идет об обратной связи управления l oop.

, мой вопрос в том, как сделать это наиболее быстрым способом с помощью Cython, что я могу определить с помощью c забавы на стороне С ++. После этого потока один из возможных способов, обеспечивающих меньшую задержку, кажется Memoryviews , но я пока не мог хорошо его понять, чтобы знать, что мне лучше написать в коде C ++ и в Файл Cython pyx. Я был бы признателен, если бы кто-нибудь мог подсказать мне это, и если бы у вас также были предложения, отличные от memoryviews, для более низкой задержки .

1 Ответ

0 голосов
/ 17 июня 2020

Когда дело доходит до оптимизации производительности, вы должны измерить!

Сначала убедитесь, что вы точно знаете, где находится ваша точка доступа. Вы можете использовать perf или Intel vTune, чтобы убедиться, что вы оптимизировали правильное местоположение.

Затем вы можете написать тест google benchmark для этой конкретной c точки доступа.

Если фрагмент - это ваша точка доступа, разделение l oop поможет вам, поскольку у вас есть непрерывный доступ к памяти.

for (int i = 0; i < 7; ++i) {
        robot_state_.q    [i] = array_that_came_from_python_side  [i+7];
}
for (int i = 0; i < 7; ++i) {
        robot_state_.dq     [i] = array_that_came_from_python_side  [i+7];
}
for (int i = 0; i < 7; ++i) {
        robot_state_.tau_J [i] = array_that_came_from_python_side  [i+14];
}

Или он может ничего не сделать, потому что в наши дни компиляторы очень умны.

Возможно, std::memcopy сделает отличную работу

std::memcpy(robot_state_.q, &array_that_came_from_python_side[0], 7);
std::memcpy(robot_state_.dq, &array_that_came_from_python_side[7], 7);
std::memcpy(robot_state_.tau_J , &array_that_came_from_python_side[14], 7);
...