Самый простой способ написать параллельные модули C / C ++ для использования в Python

Краткая справка (не обязательно)

Я работал над написанием альтернативы ( требует меньше ресурсов ?) среднее смещение Модуль C ++ для Scikit-Learn один.

Я использовал, на стороне C ++, nanoflann библиотека для построения и поиска KD-деревьев.

В основном у меня есть два массива, которые я передаю своей функции C ++ MeanShift через Cython, которая затем возвращает список найденных центров кластеров.

Оказывается, немного быстрее, примерно в 7 раз (я все еще активно работаю над этим).

Мой вопрос :

Я хотел бы распараллелить самые дорогие части моего кода C ++, такие как циклы for, используемые для конвергенции, но, поскольку этот модуль C ++ будет импортирован в python, я хотел бы сделать это в наиболее безопасном & простой способ.

Я думал об использовании OpenMP, у вас есть какие-либо предложения?

Спасибо!
Хорошего дня.

Редактировать / Кодовый фрагмент

Спасибо @ bivouac0, теперь я могу собрать все.

Сейчас я борюсь против логической / технической стороны.
Позвольте мне написать вам фрагмент кода, который я хочу распараллелить.

у меня есть std::vector<std::pair<size_t, double> > > matches вектор и довольно большой double samples[N] массив.
Я хочу использовать первый элемент пар, хранящихся в matches вектор для расчета индекса доступа к большему samples массив (см. код ниже):
Это метод, который делает это:

typedef std::vector<std::pair<size_t, double> > searchResultPair;
double* calcMean(size_t nMatches, searchResultPair matches,
double* samples) {
/*
*/
double* returnArray = new double[3];
returnArray[0] = 0;
returnArray[1] = 0;
returnArray[2] = 0;
double x = y = z = 0;
for (size_t i = 0; i < nMatches; i = i + 1) {
x = x + samples[3 * (matches[i].first)];
y = y + samples[3 * (matches[i].first) + 1];
z = z + samples[3 * (matches[i].first) + 2];
}
returnArray[0] = x/nMatches;
returnArray[1] = y/nMatches;
returnArray[2] = z/nMatches;

return(returnArray);
}

Есть ли способ одновременного доступа к matches[i].first переменная?

Я пробовал с #pragma omp parallel for reduction(+:x,y,z) num_threads(n_threads) но это снижает производительность (1 поток> 2 потока> 4 потока> 8 потоков и т. д.).

Есть ли в моем вопросе какой-то смысл? Я где-нибудь ошибаюсь?
Это может быть просто накладные расходы на управление параллельной n_threads команда для расчета частичных сумм x,y,z, так как элементы в vector хранятся в сговоре …

Я мог бы разделить вышеуказанный цикл for на 3 части и попытаться распараллелить каждую из них. Это может быть хорошей идеей?
Это вычисление вложено в while вложен в другой цикл for, и это самый важный метод всего модуля.

2

Решение

В связи с вышеупомянутыми проблемами при компиляции кода C ++ с OpenMP, вам, вероятно, просто нужно включить gomp библиотека. Вот простой скрипт setup.py, который работает для меня …

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize, build_ext
# run as... python setup.py build_ext

ext = Extension("entity_lookup",    # name of extension
["src/entity_lookup.pyx", "src/EntityLookupImpl.cpp", "src/IndexDictImpl.cpp"],
language="c++",     # this causes Pyrex/Cython to create C++ source
#include_dirs=[...],
libraries=['gomp'], # or include explicity with extra_link_args below
cmdclass = {'build_ext': build_ext},
#extra_link_args=['/usr/lib/x86_64-linux-gnu/libgomp.so.1'], # see above
extra_compile_args=['-fopenmp', '-std=c++11']
)

setup(
name = 'EntityLookup',
version = 0.4,
description = 'Package to match words and phrases to Entity labels',
ext_modules = cythonize(ext)
)

Обратите внимание на включение gomp (он же libgomp.so.1). Это где GOMP_parallel определяется.

Для компиляции сделай … python setup.py build_ext

Я всегда использовал этот код на месте (нигде не установлен), и для этого вам нужно установить ссылку на скомпилированный entity_lookup.so, который находится глубоко в каталоге «build», который создает скрипт.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]