Проблемы с пониманием неожиданного поведения в коде с OpenMP - PullRequest
1 голос
/ 09 ноября 2019

Вопрос по распараллеливанию OpenMP. Я включил урезанную версию моей функции ниже. Проблема в том, что содержимое цикла for оценивается не для всех значений uiIndex, хотя и не всегда.

  1. Я использую буфер vec_succ_status, чтобы проверить, все ли значения uiIndex оцениваются. Оказывается, это не так.
  2. Мой код не падает, он просто выходит из функции compute_Lagr_shortest_paths_from_source, не встречая ни одного из операторов выхода (-1) в определении функции ниже.
  3. Я использую g ++ 7.4.0версия на Ubunutu 14, и каждый раз, когда она терпела неудачу, есть только одно значение uiIndex, которое было пропущено. Нет никакого соответствия uiIndex, для которого функция не может быть оценена.
  4. Для программ, которые я тестировал, размер vec_group всегда равен 1, поэтому будет оцениваться только первый оператор if внутри цикла for.
  5. В свою основную функцию я включил строку omp_set_num_threads (4). Кроме того, я не установил никаких других настроек (таких как тип планировщика) для OpenMP.
  6. Кроме того, я могу заверить, что никакие 2 значения uiIndex не приводят к одному и тому же значению uiRobot, поэтому никакие 2 потока никогда не будутдолжен получить доступ к одному и тому же массиву vec_cf_graphs [uiRobot] через время существования функции.

Интересно, делаю ли я некоторые неверные предположения относительно OpenMp. Я требую, чтобы все объекты, такие как vec_cf_graphs, vec_succ_status были общими для всех потоков. Мне интересно, если мне нужно явно упомянуть их как общие, как это обычно рекомендуется. В любом случае, я думал, что способ, которым я реализовал, также достаточен. Однако мне кажется довольно странным, что некоторые значения uiIndex могут быть вообще пропущены. Я должен отметить, что я неоднократно вызываю показанную функцию, но только иногда определенные значения uiIndex пропускаются из оценки. Если кто-то может указать мне на потенциальные проблемы с моим подходом, это было бы здорово. Я рад предоставить дополнительную информацию. Спасибо.

bool compute_Lagr_shortest_paths_from_source(std::vector<Robot_CF_Graph>& vec_cf_graphs, const std::vector<std::vector<size_t>>& vec_robot_groups)
{
    size_t uiIndex;
    std::vector<bool> vec_succ_status(vec_robot_groups.size(), false);

    #pragma omp parallel for default(shared) private(uiIndex)
    for(uiIndex = 0; uiIndex < vec_robot_groups.size(); uiIndex++)
    {
        vec_succ_status[uiIndex] = false;
        const auto& vec_group = vec_robot_groups[uiIndex];

        if(1 == vec_group.size())
        {
        size_t uiRobot = vec_group[0];
        vec_cf_graphs[uiRobot].compute_shortest_path("ABC"); 
        vec_succ_status[uiIndex] = true;  
        }
        else          
        {            
        std::cout<< "Tag: Code should not have entered this block"<<endl;
        exit(-1);                       
        }

        if(false == vec_succ_status[uiIndex])
        {
        std::cout<< "It is not possible for this to happen \n";
        exit(-1);
        }
    }   

    return true;     
}

1 Ответ

3 голосов
/ 11 ноября 2019

Вы одновременно пишете в vector<bool>, который не является «нормальным» vector. Имеет оптимизацию внутренней памяти. Это неопределенное поведение.

См. Подробное обоснование здесь:

Запись одновременно вектор

Чем vector<bool> отличается от других vector s можно найти здесь:

https://en.cppreference.com/w/cpp/container/vector_bool

Просто использовать vector<char> с 0 или 1, представляющим истину или ложь, - самый простой способ решить эту проблему. Другие варианты обсуждаются здесь, если вы хотите иметь более элегантный код:

Альтернатива вектору

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...