Я использую openMP для параллелизации нескольких утверждений. Я использую параллель для конструкции. Распараллеленные цикл выглядит следующим образом:openMP - необходимость в атомарных или сокращающих предложениях
double solverFunction::apply(double* parameters_ , Model* varModel_)
{
double functionEvaluation = 0;
Command* command_ = 0;
Model* model_ = 0;
#pragma omp parallel for shared (functionEvaluation) private (model_,command_)
for (int i=rowStart;i<rowEnd+1;i++)
{
model_ = new Model(varModel_);
model_->addVariable("i", i);
model_->addVariable("j", 1);
command_ = formulaCommand->duplicate(model_);
functionEvaluation += command_->execute().toDouble();
}
}
Это workly в среднем. Время исполнения резко уменьшено, а результат как ожидалось. Тем не менее, время от времени, особенно для больших задач (большого числа итераций над I, большое количество данных для копирования в копии вызова конструктора
model_ = new Model(varModel_);
, другие?), Он разбился. Вызов стека заканчивается в классах, таких как qAtomicBasic (это программа, написанная на C++/Qt), QHash, и у меня есть идея, что он выходит из строя из-за одновременного доступа для чтения/записи в памяти.
HOWEVER, model_ и command_ являются частными, так что каждый поток имеет дело с копией каждого. В переменной model_ я копирую varModel_, так что указатель, переданный в аргументе, не изменяется нитями. Аналогично, command_ является копией переменной-члена formulaCommand (дубликат - это грубоватый конструктор копирования).
Возможные недостатки в моем коде я идентифицированные в
functionEvaluation может быть модифицирован несколькими потоками одновременно
конструктор копирования в заявлении
model_ = новая модель (varModel_);
читает элементы для varModel_ в памяти для создания нового экземпляра (model_). Параллельный доступ к членам данных varModel_ может произойти, хотя это не касается изменения их значения здесь, а только их чтения (затрагивающих их для других переменных).
Кроме того, я вижу два усовершенствования только (что я не могу проверить, пока несколько дней, но я прошу совета в любом случае):
добавить атомное положение, так что functionEvalution не одновременно написано в
добавить сокращение оператора (+, functionEvaluation), так что параллелизм в отношении доступа к functionEvaluation рассматривается автоматически
ли ю Решения ese, похоже, точно решают проблему и более эффективны в целом? Где проблема может быть связана с кодом, который я написал? Что такое решения?
Большое спасибо!
Большое спасибо! Konrad, я не вижу, как обойтись без указателей: вызов для копирования конструктора 'Model()' принимает аргумент, который является указателем на модель, а 'duplicate()' одинаково принимает указатель на команду. Является ли это более непрерывным или непрерывным, чтобы использовать указатели, даже если я удалю их внутри цикла? – octoback
@dlib Первый вопрос: почему эти функции принимают указатели в качестве аргументов? Но если это невозможно изменить, вы можете сделать именно то, что вы написали в своем комментарии. Использование распределения кучи здесь просто не выгодно для распределения стека, делает вещи более сложными (ручное управление памятью) и добавляет небольшие накладные расходы. Кроме того, см. Мой обновленный ответ, я бы забыл еще одну большую (!) Ошибку в вашем коде раньше. –
Это не ошибка, это недоразумение копирования (стыд), я изменил выше. Я не вижу, как использовать распределение стека здесь. Model (& model_) не подходит, поскольку я хочу скопировать varModel внутри новой модели экземпляра_; Я не могу работать без конструктора копирования, то есть с новым. – octoback