Многопоточность в С++ программе (Складирование результатов тредов в векторе)

Модератор: Модераторы разделов

Ответить
Аватара пользователя
Tema
Сообщения: 143

Многопоточность в С++ программе

Сообщение Tema »

Доброе утро.

Продолжаю знакомство с c++. Пришла пора улучшить программу добавлением многопоточности.
Проштудировал "C++ Programming Language" by Stroustrup.
Вынес следующие тезисы:
1. Локи бьют по перфомансу программы. Необходимо снизить их колличество, а лучше избавиться(существуют варианты для экспертов, но это мимо кассы)
2. Передавать указатель на объект в тред - плохая практика. Лучше использовать future, promise, async() чтобы получить то, что тред должен вернуть.
3. Существует некое количество тредов, котороедаст максимальный прирост к производительности. Этот показатель зависит от железа.

Сложности испытываю с тем, как следуя этим нехитрым правилам внедрить многопоточность в свою программу:
Исходные данные хранятся в 2д векторе:

Код: Выделить всё

=A2*2          =8+2
=A1/4          =B1


Так же существует второй 2д вектор такого же размера, где хранятся умные указатели на объекты типа Cell.
У класса Cell:

Код: Выделить всё

string input; //Это заполняется конструктором и равняется значению в первом векторе на такой же позиции элемента(x,y)
string output;//Это вычисляется методом eval
void eval();//Производит вычисления из input и заносит его в output. при этом иногда читаются доп значения из первого вектора(если ссылка, например)


Сейчас я циклом прохожу по второму вектору и поочередно дергаю метод eval() у каждого объекта по указателю.

Хотелось бы запускать eval() в разных потоках, но чтобы их количество(потоков) было оптимальным.
На сколько я понял, тут необходимо использовать async(), т.к. он сам управляет количеством потоков и он умеет возвращать результат работы потока.
Проблема лишь в том, как это сработает при общем доступе ко второму вектору?
Я думаю, что не должно быть никаких data races т.к. мы ничего не читаем со второго вектора(окромя текущего значения input), в основном только пишем и только 1 поток будет писать в одну ячейку. С другой же стороны, вектор не тред сейф, если мы пишем в него в несколько потоков.

Подскажите, пожалуйста, как лучше поступить в такой ситуации.

Спасибо заранее.
Спасибо сказали:
Аватара пользователя
Tema
Сообщения: 143

Re: Многопоточность в С++ программе

Сообщение Tema »

без локов считает что попало. Еще раз почитал про data races, там явно написано, что если в одну память имеет параллельный доступ и хотя бы 1 из тредов пишет - будут дата рейсы(странно, что я это забыл).
Попробую через async().

Код: Выделить всё

void FormulaCell::evaluate()
{
    auto fut = std::async(std::launch::async, [&] () {return parser->parseLine(inputValue, *values);});
    outputValue = fut.get();
}

Думаю, это треш. Ведь оно будет ждать на строке outputValue = fut.get(); для каждого элемента вектора... Надо как-то что ли потом собирать как-то..

PS:
Блиц-вопрос: где принято включать доп библиотеки? в заголовочном файле(.h) или в сорс файле(.cpp)?
Спасибо сказали:
Аватара пользователя
Tema
Сообщения: 143

Re: Многопоточность в С++ программе

Сообщение Tema »

Код: Выделить всё

std::future<std::string> theFuture;
bool wasExecuted;

Код: Выделить всё

void evaluate()
{
    theFuture = std::async(std::launch::async, [&] () {return parser->parseLine(inputValue, *values);});
}
std:: string & getOutput()
{
    if (wasExecuted)
        return outputValue;
    outputValue = theFuture.get();
    wasExecuted = true;
    return outputValue;
}


Вот таким нехитрым способом удалось(я надеюсь) добиться параллельной калькуляции ячеек во втором векторе.
Кстати говоря, а как можно убедиться, что действительно считается в параллели?

Спасибо
Спасибо сказали:
Аватара пользователя
Tema
Сообщения: 143

Re: Многопоточность в С++ программе

Сообщение Tema »

добавил фичу: загрузка данных из csv. при 6000 строк в исходных данных с тредингом(который я выше описал) работает 60-65 сек. А без него 30-40 сек. что-то тут не то...

Апдейт:
Закоментил /*std::launch::async,*/ и получил 20 секунд. Хотя время колеблется... как бы проверить нормально?
Спасибо сказали:
Ответить