Премини към съдържанието
miracle boy

Малко помощ за Multithreading / boost библиотеката

Препоръчан отговор


Здравейте, трябва ми малко помощ за една малка реализация с помощта  на boost библиотеката. Имам една съвсем проста реализация на с++, функция, която умножава множество от числа. Тази кратка функция, трябва да реализирам така че тя да се изпълнява от две нишки,едновременно. Реализацията с една нишка я правя, но с две нещо не мога да разреша проблема. Много ще съм благодарен, ако някой занимавал се с тази библиотека и с Multithreading може да ми помогне. Ето и кодът който съм написал до тук.

 

 
#include <boost/cstdint.hpp> #include <boost/thread.hpp>#include <iostream>  boost::uint64_t sum = 1;  void math(){	 for (int i = 1; i <= 50 -1 ; i++) 		sum *= i; }int main() {     boost::thread t (math);  t.join();   std::cout << sum << std::endl;   return 0;} 

 

 

 

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Здравейте, трябва ми малко помощ за една малка реализация с помощта  на boost библиотеката. Имам една съвсем проста реализация на с++, функция, която умножава множество от числа. Тази кратка функция, трябва да реализирам така че тя да се изпълнява от две нишки,едновременно. Реализацията с една нишка я правя, но с две нещо не мога да разреша проблема. Много ще съм благодарен, ако някой занимавал се с тази библиотека и с Multithreading може да ми помогне. Ето и кодът който съм написал до тук.

Може ли да опишеш по-точно какъв проблем не може да разрешиш?

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Може ли да опишеш по-точно какъв проблем не може да разрешиш?

Проблема който не мога да разреша е следния, искам като "извикам" за изпълнение math(), тя да се изпълнява от две нишки, или един вид ако процесора ни е двуядрен, двете ядра да се натоварват едновременно, а не само едното, а другото да чака.

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Проблема който не мога да разреша е следния, искам като "извикам" за изпълнение math(), тя да се изпълнява от две нишки, или един вид ако процесора ни е двуядрен, двете ядра да се натоварват едновременно, а не само едното, а другото да чака.

Значи, тук виждам доста проблеми.Първо, създаваш само една нишка.Второ, извън замисъла на boost::thread е да се интересува от наличието/броя на ядрата на процесора. Това е отговорност на потребителя, т.е. ти си мисли, как ще разбереш колко са ядрата и колко нишки ще ползваш и изобщо има ли и каква е връзката между нишките и ядрата. В крайна сметка не е задължително, само твоят процес да работи на системата, или пък ботълнека да е процесора, нали?Трето, нишките на boost са точно това, т.е просто нишки. За разлика от някои подходи за паралелизиране в OpenMP или Intel Threading Building Blocks, които автоматично ще ти разбият цикъла на еди колко си части, тука няма такова нещо. Трябва сам да си разпределиш работата и пускайки всяка нова нишка, да измислиш начин да кажеш на функицята си, коя част от работата да свърши в точно този контекст и накрая, след като приключат работа, да обединиш резултата от всичките.Четвърто, не може просто така да ползваш глобални променливи в многонишкова програма. Ако двете ядра решат да работят с променливата sum (sum??? може би си искал да кажеш product?) едновременно, няма кой да ги спре и резултатът ще бъде напълно непредвидим. Не се прави така. Или трябва всяка от нишките да си ползва нейна променлива за нейната част от резултата, или трябва да я защитиш, например с mutex. Прочети за защитаване на ресурси.

  • Харесва ми 2

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Благодаря за съветите. Ще прочета още малко и ще се разровя за още информация. Да се надяваме че ще се справя.

 

Благодаря отново flare!


Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Благодаря за съветите. Ще прочета още малко и ще се разровя за още информация. Да се надяваме че ще се справя.

 

Благодаря отново flare!

Най-бързо ще постигнеш това, което искаш, като вместо функция, си направиш клас-функтор (т.е. да има предефиниран оператор "()"). вътре в класа да има член променливи за интервала и резултата. С конструктора ги инициализираш. Предефинираният оператор ще прави това, което в момента ти прави функцията math, само че не от 0-50 ами колкото си му задал от конструктора и ще го записва в полето за резултат. И един гет метод да го връща накрая. Правиш си един масив или списък от нишки (колкото искаш да са) и в цикъл създаваш по един обект от горепосочения клас с поредния интервал и ги подаваш. След това в нов(да не го направиш в същия :P) цикъл ги джойнваш и с гет метода издърпваш резултата от всяка и ги комбинираш. Това е. Не е сложно.

  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Примерно решение, което използва boost::packaged_task и boost::future. Тествано е с GCC-4.8 и boost 1.55. Компилира се с

 

g++ -pthread -std=c++11 -lboost_system -lboost_thread mult.c -o mult

 

Повече информация може да намериш на http://www.boost.org/doc/libs/1_55_0/doc/html/thread/synchronization.html#thread.synchronization.futures и

http://stackoverflow.com/questions/19572140/how-do-i-utilize-boostpackaged-task-function-parameters-and-boostasioio

#include <boost/cstdint.hpp> #include <boost/thread.hpp>#include <iostream> #include <vector>typedef std::vector<boost::unique_future<int64_t> > TaskFuture_t;int64_t math_worker(int start, int end){    int64_t sum = 1;    for (int i = start; i < end; i++) {        sum *= i;     }        return sum;}int main() {     int numThreads = 0;    int threadCounter;    int64_t totalSum = 1;    int startVal;    int endVal;    int incr;    int incrRemain;    int endValLoop;    TaskFuture_t futures;    std::cout << "How many threads should we run" << std::endl;    std::cout << "> ";        std::cin >> numThreads;        std::cout << "Start value" << std::endl;    std::cout << "> ";        std::cin >> startVal;        std::cout << "End value" << std::endl;    std::cout << "> ";        std::cin >> endVal;    // from the start and end value get the increment to be used in the loop    incr = ((endVal + 1) - startVal);    if (incr < 0) {        std::cout << "Error: Invalid start and end values" << std::endl;        exit (-1);    }         // calculate the remainder for the last loop    incrRemain = incr % numThreads;    incr /= numThreads;    endValLoop = startVal;    for (threadCounter = 0; threadCounter < numThreads; threadCounter++) {            endValLoop += incr;                if (threadCounter == numThreads - 1) {            // for the last itteration include the remainder            endValLoop += incrRemain;        }                std::cout << "start " << (incr*threadCounter + startVal) << " end " <<  endValLoop << std::endl;                 // create a packaged task with 2 parameters (start and stop for the multiplication loop)        boost::packaged_task<int64_t> pt(boost::bind(math_worker, (incr*threadCounter + startVal), endValLoop));                // save the future (return value from the thread) in a vector        futures.push_back(pt.get_future());                // kick the task        boost::thread task(boost::move(pt));    }            // wait for everything to complete    boost::wait_for_all(futures.begin(), futures.end());    // get the final result    for (size_t futSize = 0; futSize < futures.size(); futSize++) {        totalSum *= futures[futSize].get();    }    std::cout << totalSum << std::endl;     return 0;} 

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Благодаря и на двамата за бързите и много полезни за мен отговори. :) 

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Регистрирайте се или влезете в профила си за да коментирате

Трябва да имате регистрация за да може да коментирате това

Регистрирайте се

Създайте нова регистрация в нашия форум. Лесно е!

Нова регистрация

Вход

Имате регистрация? Влезте от тук.

Вход

×

Информация

Поставихме бисквитки на устройството ви за най-добро потребителско изживяване. Можете да промените настройките си за бисквитки, или в противен случай приемаме, че сте съгласни с нашите условия за ползване.