170 похожих чатов

Добрый вечер, у меня вопрос по поводу многопоточности thread/async/future, подскажите,

могу ли я его тут задать?

81 ответов

29 просмотров

Да

Hidanio- Автор вопроса

Надеюсь что да) У меня такой вопрос https://pastebin.com/swHkE4Vj Начал изучать многопоточность и пытаюсь сделать суммирование столбцов матрицы, каждый в параллель, но что-то мудрю-мудрю уже сутки и не могу понять до конца как правильно нужно работать с async/future или thread (через thread получилось, но он только один, а я хочу чтобы каждый столбец матрицы считался параллельно, те в рантайме определял сколько столбцов - столько и потоков) Может кто-нибудь помочь, да направить на путь истинный? P.S. Делаю изначально считывание из файла, но там в main заккоментил

Hidanio
Надеюсь что да) У меня такой вопрос https://pasteb...

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

Hidanio
Надеюсь что да) У меня такой вопрос https://pasteb...

std::thread th1(...); th1.join() Вот в этом по факту смысла нет - получается синхронное выполнение функции потока. А вообще если хочется, чтобы параллельно считались суммы по столбцам, то в функцию потока и надо впихивать тогда один столбец, который суммируется в этом потоке

Hidanio- Автор вопроса
Слава
Мьютекс для чего?

Ну как я понял его нужно для синхронизации использовать при доступе к одному объекту, те к моей матрице

Hidanio
Ну как я понял его нужно для синхронизации использ...

Если конкурентно только читаешь, то синхронизация не нужна

Hidanio- Автор вопроса
Слава
А ты что читаешь за книгу?

Энтони Уильямс + интернет + хабр

Hidanio- Автор вопроса
Hidanio
Энтони Уильямс + интернет + хабр

Пытаюсь на практике тыкаться потихоньку

Hidanio
Ну как я понял его нужно для синхронизации использ...

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

Hidanio- Автор вопроса
Georgy Firsov
std::thread th1(...); th1.join() Вот в этом по фа...

То есть он всё равно считает каждый столбец в одном потоке?

Hidanio
То есть он всё равно считает каждый столбец в одно...

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

Hidanio
Ну как я понял его нужно для синхронизации использ...

У тебя тут же доступа нет к одному объекту. Тут у тебя потоки каждый на своем столбце и никто одновременно одну ячейку не изменяет вместе с другим потоком. Тут проблема конечно с кэшами, но не думаю что сильно волнует сейчас

Hidanio- Автор вопроса
Georgy Firsov
Ну ты запускаешь поток и сразу же блокируешь вызыв...

Кажется понял) То есть пока не завершится вычисление одного столбца - остальные ждут?

Hidanio
Кажется понял) То есть пока не завершится вычислен...

Остальные, более того, и не создаются даже ещё join - блокирующая операция

Hidanio- Автор вопроса
Слава
Знаешь что джоин делает?

Закрывает потоки, те блокирует как я понял и потом закрывает

Hidanio
Закрывает потоки, те блокирует как я понял и потом...

Нет. Вот есть у тебя вызывающий join поток и сторонний поток (для которого этот join вызывается) join блокирует вызывающий поток до тех пор, пока не завершится тот сторонний поток поток А на любые другие потоки, очевидно, никакого влияния нет

Hidanio- Автор вопроса
Hidanio
https://pastebin.com/ut7TBJYU

Я вот подправил только что, сделал вектор тредов чтобы запустить в одно время

Hidanio- Автор вопроса
Hidanio
Я вот подправил только что, сделал вектор тредов ч...

Ага, то есть на 25-й строчке threads.emplace_back(ColumnSum, matrix, i); надо заменить на: threads.emplace_back(ColumnSum, std::cref (matrix), std::cref(i));

Hidanio
Я вот подправил только что, сделал вектор тредов ч...

Ну вот это уже ок (но про cref глянь) Только вот фьючи там зачем - неясно. К слову, любое непойманное исключение внутри функции потока для std::thread - вызов std::terminate

Hidanio- Автор вопроса
Georgy Firsov
Ээээ, i зачем по ссылке то?

но у меня в сигнатуре она тоже const & Да и почему нет? Зачем лишнее копирование?

Hidanio
но у меня в сигнатуре она тоже const & Да и почему...

Для тривиальных типов (да и тех, что в регистр влезают) копирование - одна машинная инструкция И их принято как раз по значению передавать

Hidanio- Автор вопроса
Georgy Firsov
Для тривиальных типов (да и тех, что в регистр вле...

Спасибо! Тогда ещё вопрос: У меня там закоменчено с async и оно падало с ошибкой. Как вообще лучше (и правильнее) его использовать?

Hidanio- Автор вопроса
Georgy Firsov
С какой ошибкой?

У меня просто вижуалка закрывалась)))

Hidanio- Автор вопроса
Hidanio
Ага, то есть на 25-й строчке threads.emplace_back(...

Ты же понимаешь что у всех тредов будет ссылка на одну протухшую переменную? При cref

Hidanio
А почему они не нужны? (фьючи)

Ну потому что у тебя и так задача в тредах выполняется

Слава
Ты же понимаешь что у всех тредов будет ссылка на ...

А вот, кстати, поэтому и падает std::async скорее всего Ибо захват i в лямбду по ссылке идёт, а дальше уже UB

Georgy Firsov
А вот, кстати, поэтому и падает std::async скорее ...

Не знаю что там конечно падать может. Просто хз что выведет в итоге

Hidanio- Автор вопроса
Слава
Ты же понимаешь что у всех тредов будет ссылка на ...

0_0 Да, матрицу по ссылке - ок, а i - не ок (упал с ошибкой) Можете подробнее объяснить?

Georgy Firsov
Ну UB на то и UB

Не знаю просто из-за чего упасть может 🤷 и что там происходит такого

Hidanio
0_0 Да, матрицу по ссылке - ок, а i - не ок (упал ...

Там, по выходе из цикла i больше нет, а вот лямбды ещё жить могут А ссылка на i в них живёт

Слава
Не знаю просто из-за чего упасть может 🤷 и что там...

Как вариант async решает выполниться отложенно (когда get позовут), а там ссылка на i в лямбдах

Georgy Firsov
Как вариант async решает выполниться отложенно (ко...

Там же i не меняется а просто читается. Там просто мусор

Слава
Там же i не меняется а просто читается. Там просто...

Ну читать по битой ссылке - UB Хотя по идее i жила на стеке, адрес на стек и будет указывать... Доступ для чтения там будет. Впрочем, опять рассуждения о том, что при UB происходит

Hidanio- Автор вопроса
Georgy Firsov
Как вариант async решает выполниться отложенно (ко...

Так, треды вроде заполняются и теперь всё оки, а как теперь мне результаты из вектора тредов записать в vector<int>?

Hidanio
Так, треды вроде заполняются и теперь всё оки, а к...

Вручную использовать std::future/std::promise std::thread игнорирует результат функции Ну или выходные параметры функции прикрутить... Но это такая себе история, лучше не надо)

Hidanio- Автор вопроса
Georgy Firsov
Вручную использовать std::future/std::promise std:...

Можно на моём примере, если не сложно Не очень с фьючерами понимаю как это сделать, копнул только чуть-чуть

Hidanio
Можно на моём примере, если не сложно Не очень с ф...

Чекаем примеры в доке: https://en.cppreference.com/w/cpp/thread/future Кстати, там же ещё про std::packaged_task написано. Оно чуть больше подходит

Hidanio- Автор вопроса
Georgy Firsov
Чекаем примеры в доке: https://en.cppreference.com...

Буду разбираться, спасибо! А можете литературу посоветовать ещё хорошую, где, особенно много примеров

Hidanio
Буду разбираться, спасибо! А можете литературу пос...

То ли в каком-то закрепе, то ли в описании чата есть ссылка на книжки По параллельщине - ты правильную книжку выбрал - ту, что от Вильямса

Hidanio- Автор вопроса
Hidanio- Автор вопроса
Georgy Firsov
То ли в каком-то закрепе, то ли в описании чата ес...

std::vector<int> result; std::vector<std::future<int>> futures; // futures.reserve(matrix.size()); std::vector<std::thread> threads; for (size_t i = 0; i < matrix[0].size(); i++) { std::packaged_task<int(const std::vector<std::vector<int>>&, int)> task(ColumnSum); // std::future<int> result1 = task.get_future(); std::future<int> ret = task.get_future(); threads.emplace_back(std::move(task)); futures.push_back(ret); //threads.emplace_back(ColumnSum, std::cref(matrix), i); } Пытаюсь делать по примеру из доки, но падает с ошибкой: C2280 'std::future<int>::future(const std::future<int> &)': attempting to reference a deleted function По гуглу не понимаю в чём ошибка

Hidanio
std::vector<int> result; std::vector<std::fu...

std::future некопируемый тип, о чем тебе и сказано в ошибке А push_back создает элемент, а потом в него копирует аргумент

Hidanio
И как быть тогда?

futures.emplace_back(std::move(ret)); Чем вариант строкой выше не понравился?

Hidanio
Надеюсь что да) У меня такой вопрос https://pasteb...

У тебя мьютекс, он не нужен в данном случае, так как матрица read only в процессе вычисления

Hidanio- Автор вопроса
Georgy Firsov
futures.emplace_back(std::move(ret)); Чем вариант...

Error C2672 'invoke': no matching overloaded function found Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&) noexcept(<expr>)

Hidanio
Надеюсь что да) У меня такой вопрос https://pasteb...

Ещё, если бы мьютекс был нужен, его надо было бы делать один на всю матрицу скорее всего

Hidanio- Автор вопроса
Ilya Zviagin
Ещё, если бы мьютекс был нужен, его надо было бы д...

Спасибо, мне этот момент уже подсказали!

Hidanio- Автор вопроса
Ilya Zviagin
Ещё что-то не ясно ?

Да, вылезли новые проблемы

Hidanio- Автор вопроса
Hidanio
Да, вылезли новые проблемы

std::vector<int> result; std::vector<std::future<int>> futures; // futures.reserve(matrix.size()); std::vector<std::thread> threads; for (size_t i = 0; i < matrix[0].size(); i++) { std::packaged_task<int(const std::vector<std::vector<int>>&, int)> task(ColumnSum); // std::future<int> result1 = task.get_future(); std::future<int> ret = task.get_future(); threads.emplace_back(std::move(ret)); // futures.push_back(ret); //threads.emplace_back(ColumnSum, std::cref(matrix), i); }

Hidanio- Автор вопроса
Hidanio
std::vector<int> result; std::vector<std::fut...

Error C2672 'invoke': no matching overloaded function found Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&) noexcept(<expr>)

Hidanio- Автор вопроса
Hidanio
https://pastebin.com/baRjd5sf

Тип ColumnSum не совпадает с тем, что в параметре шаблона таски указан

Hidanio- Автор вопроса
Georgy Firsov
Тип ColumnSum не совпадает с тем, что в параметре ...

Да, блин, я поправил, но всё та же ошибка

Hidanio
Да, блин, я поправил, но всё та же ошибка

У тебя там мракобесие с векторами получилось. Во-первых, фьючи куда-то не туда складируются Во-вторых, а я чет не вижу запуска тасок Ну да, ты в threads зачем-то кладешь фьючи. std::thread конструируется от std::future и пытается вызвать её (sic!). Ясно, что std::future - ни разу не Callable, вот и ошибка

Hidanio
std::vector<int> result; std::vector<std::fut...

А зачем тебе сразу и треды, и фьючи?

Ilya Zviagin
А зачем тебе сразу и треды, и фьючи?

Тренируется человек и так и так делать помеременно

Hidanio
std::vector<int> result; std::vector<std::fut...

Ты это как, по наитию писал или как? Почему именно так?

Hidanio- Автор вопроса
Ilya Zviagin
Ты это как, по наитию писал или как? Почему именно...

Пытаюсь освоить многопоточку, чтобы оно заработало, разные варианты перебираю...

Hidanio
Пытаюсь освоить многопоточку, чтобы оно заработало...

Там их два всего., либо треды, либо фьючи

Hidanio- Автор вопроса
Ilya Zviagin
Там их два всего., либо треды, либо фьючи

Ага, а как мне тогда заполнить vector<int> результатами из threads?

Hidanio- Автор вопроса
Georgy Firsov
У тебя там мракобесие с векторами получилось. Во-п...

Да, кажется понял что-то из вашего сообщения Но как мне тогда из треда получить значение и записать его в вектор? Вы говорили как-то future отдельно дёргать, вот я и попытался Создал таску в package, task.get_future(); по идее должен получаю его значение? и потом в вектор пытаться? Но тогда это же будет один поток...

Hidanio
Да, кажется понял что-то из вашего сообщения Но ка...

У фьючи есть метод get, который и возвращает значение, полученное из другого потока, из другой части программы, из космоса, etc. Идея в чем: создаем таски, получаем фьючи, запускаем таски в потоках, джойним потоки, а дальше примерно так: std::vector<int> results; std::transform(futures.cbegin(), futures.cend(), std::back_inserter(results), [](const auto& f) { return f.get(); }); reserve ещё стоит вызвать

Hidanio- Автор вопроса
Georgy Firsov
У фьючи есть метод get, который и возвращает значе...

std::packaged_task<int(const std::vector<std::vector<int>>&, const int&)> task(ColumnSum); std::future<int> res1 = task.get_future(); std::thread t(task(std::cref(matrix), i)); Так? Ошибки те же самые... Создали таску, получили фьючу, пытаемся получить фьючу и отправить в поток

Hidanio- Автор вопроса
Georgy Firsov
У фьючи есть метод get, который и возвращает значе...

Храни тебя господь, поставлю свечку за тебя Что-то получилось с таким кодом: std::packaged_task<int(const std::vector<std::vector<int>>&, const int&)> task(ColumnSum); futures.push_back(task.get_future()); threads.emplace_back(std::move(task),std::cref(matrix), i);

Hidanio- Автор вопроса
Hidanio
Но пока что только один поток...

https://github.com/progschj/ThreadPool самый простой

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Гайс, вопрос для разносторонее развитых: читаю стрим с юарта, нада выделять с него фреймы с определенной структурой, если ли чо готовое, или долбаться с ринг буффером? нада у...
Vitaly
9
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
длина пакета фиксированная, или меняется?
Okhsunrog
7
Карта сайта