Я работал над написанием альтернативы ( требует меньше ресурсов ?) среднее смещение Модуль 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, и это самый важный метод всего модуля.
В связи с вышеупомянутыми проблемами при компиляции кода 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», который создает скрипт.
Других решений пока нет …