LINUX.ORG.RU

СИ++ Проблема в распараллеливании вычислений

 , ,


0

1

имеется проект
запускной файл
там выполняется функция genFlop(), которая описана тут
в ней выполняется моя попытка распараллелить вычисления.
если оставить всего один поток, то все выполняется отлично, все значения вычисляются. Однако, если запустить хатя бы два потока, то начинается недосчет значений. Точность важна.
Предположительно несколько потоков имеют доступ к одной сущности из-за чего для другого параллельного потока она корруптится и получается неправильное значение.
не могу понять, что за сущность так влияет подобным образом.
в самой функции подсчетов я поставил мьютексы на накопители, которыми и осуществляется подсчет.

Есть ли у кого какие мнения почему подсчеты не верны при параллелизме и всегда разные?

★★

потому что у тебя там полная фигня и по идее она должна падать. впрочем, это опционально, ибо UB.

ты обращаешься из разных потоков к функциям, которые дёргают вектор. а он ни разу не thread-safe для записи.

в общем, тебе надо начинать с изучения азов параллельного программирования.

Iron_Bug ★★★★★
()
Ответ на: комментарий от Iron_Bug

в общем, тебе надо начинать с изучения азов параллельного программирования.

енто понятно, не могу найти в одном месте что то дельное по данному поводу. про сами классы, функции и их использование я в принцыпе нашел инфу, а вот как именно необходимо для нормального программирования нет.
касательно векторов — они же при параллельных вычислениях тоже копируются в память к каждому потоку? если да, то почему они не тред-сейф?

safocl ★★
() автор топика
Ответ на: комментарий от safocl

а, ты его ещё и копируешь. это я думала, что у тебя там указатели.

но всё равно у тебя там престранный метод рефраш (Refrash), который обращается к какому-то внутреннему вектору, вообще без использования board. и ты чистишь этот вектор и потом вставляешь туда элемент, а счётчик count начинает указывать абы куда. в общем, там какая-то лажа.

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 1)
Ответ на: комментарий от Iron_Bug

Refrash я переименую на gen() так думаю будет лучше)))
в классе Deck, у которого ентот метод рефраш, есть вектор елементов Card (карта), который хранит колоду карт. Соответственно она должна динамически меняться с зависимостями от руки (hero_h) и борда (board), исключая карты в их содержании.
Счетчик count всего лишь число, енто не итератор (в привычном си++ смысле) вектора, по ентому он уже после составления колоды (Deck deck.Refrash) подставляется в deck.at(count).
По ентому я не могу найти причину UB.
самого объекта, к которому идет неправильное обращение не могу найти. даж хз, вроде все норм. вроде исключил обращение нескольких потоков одновременно к одной сущности.

safocl ★★
() автор топика
Ответ на: комментарий от safocl

дело не в переименовании. зачем ты туда передаёшь board? он там не используется. зато ты чистишь, а потом практически случайным образом заполняешь внутренний вектор в deck. а потом пытаешься обратиться по какому-то смещению в нём. и вообще не факт, что ты не вылезешь за его пределы.

у тебя там нарушена логика.

Iron_Bug ★★★★★
()
Ответ на: комментарий от Iron_Bug

тут получается проверяет на совпадение карты, кандидата на добавление в колоду со всеми картами на доске. тут описание функции брутфорса на совпадение.
Т.е. если карта уже присутствует на борде, то ее не надо добавлять в колоду, ибо будет дубликат, что не допустимо.
так логика вроде нормальная... хз как еще реализовать можно было.
ессесна думаю над модернизацией кода, однако, в данный момент надо именно добиться многопоточности, ибо далее исполнял бы код в однопоточном варианте и уже в будущем исправления на многопоток могли бы затронуть большего времени.
внутренний вектор deckArr заполняется с 2(dhsc) по A(dhsc) перебором за исключением тех карт, которые уже присутствуют на руках или борде.

safocl ★★
() автор топика
Последнее исправление: safocl (всего исправлений: 1)

Как установить количество потоков, не изучая все исходники?

anonymous
()

бери Williams A. - C++ Concurrency in Action (не знаю есть ли перевод). там и про твою предыдущую боль (копирование аргументов в конструкторе std::thread) подробно написано.

anonymous
()
Ответ на: комментарий от safocl
  • 1)Как минимум, вот тут у тебя бага с мьютексом, он точно не должен быть локальным. Так как в потоках у тебя будет N разных мьютексов, а должен быть один общий для всех потоков.
    void sumHandStrength(const Hand & hero_h, const vector<Card> & board,
                         unsigned long long & hight, unsigned long long & pair, unsigned long long & twopair,
                         unsigned long long & set, unsigned long long & strait, unsigned long long & flash, 
                         unsigned long long & fullhouse, unsigned long long & kare, unsigned long long & straitflash)
    {
        std::mutex mt1;
    }
    
  • 2) т.к. у тебя простые типы (int/long) вместо оборачивания в объект синхронизации (мьютекс) можно использовать атомарные типы данных
art_corp
()
Ответ на: комментарий от safocl

в мультитреде не видит дебагер значений переменных

У тебя в Makefile стоит -O2 и -g поправь на -O0 -g и, возможно, получится нормально отлаживаться,но это не точно :)

art_corp
()
Последнее исправление: art_corp (всего исправлений: 1)
Ответ на: комментарий от art_corp

Ещё ему можно включить thread sanitizer (-fsanitize=thread), тогда и без запуска отладчика можно проблему увидеть (-O0 лишним и здесь не должен быть).

xaizek ★★★★★
()
Ответ на: комментарий от art_corp

да, действительно, и общий мьютекс и атомарные переменные решили данную трабблу.
остановился на атомарных переменных.
код перезалил, если у кого есть еще какието наставления на истинный путь, буду слушать.

safocl ★★
() автор топика
Ответ на: комментарий от art_corp

о, а это полезно тоже, буду знать, что оптимизация затрудняет нормальную работу дебагеру

safocl ★★
() автор топика
Ответ на: комментарий от xaizek

Ещё ему можно включить thread sanitizer (-fsanitize=thread)

ого она замедляет выполнение как.
как я понял енто тесты на баги?

safocl ★★
() автор топика
Ответ на: комментарий от safocl

Да, но во время исполнения. Помогает, если есть юнит-тесты и запускаются под разными санитайзерами.

xaizek ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.