Na pewne zadanie obliczeniowe przewidziane jest X czasu. Jeżeli się uda je rozwiązać to w porządku, a jeżeli nie to trudno - grunt, żeby nie przekroczyć czasu. Chciałbym rozwiązać wiele takich zadań, każde w osobnym wątku. Mam już coś takiego:
list threads; for (problem : problems) { ____threads.push_back(solve(problem)); } for (thread : threads) { ____thread.join(); } I to ścierwo działa, bardzo ładnie działa, ale oczywiście skończy jak skończy i zwraca wszystkie rozwiązania (są one wkładane do kontenera - monitora). Wie ktoś jak inteligentnie zmodyfikować to rozwiązanie tak, żeby przestrzegało ograniczeń czasowych? Podejrzewam, że jest to dość typowy przypadek dlatego nie chce wymyślać koła na nowo.
EDIT: Czas rozwiązania problemu bardzo się różni dla poszczególnych przypadków dlatego zawsze mam pewność, że przy racjonalnym czasie część zdąży się rozwiązać, a część nie.
@Onoki: std::thread nie ma bodaj abort'a, wiec jedyne co zostaje to wstawic jakies progress tracker'y do zadania, ktore na zadanie watku glownego rzucaja wyjatek (musisz go zlapac w watku)
@losiul: Problemem jest funkcja solve(), która może wykonywać się zbyt długo. Jestem w stanie sprawdzić czy czas został przekroczony bezpośrednio przed nią i po niej, ale to mnie nie ustawia. Miałem nadzieję na kontrolę czasu w innym wątku (głównym) i uśmiercenie tych, które jeszcze pracują kiedy czas się skończy. :<
ach, nie uzywaj list, to jest praktycznie bez sensu w 99% wypadkow ; )
Co do listy, vector jest szybszy prawie w kazdym wypadku
@losiul: To ciekawe. Byłem przekonany, że lista jest zbudowana tak, że każdy poprzednik zawiera wskaźnik na następnik (i być może odwrotnie), a elementy mogą sobie być rozrzucone po pamięci. Wektor natomiast musi być przebudowany (skopiowany w inne miejsce) po każdej zmianie rozmiaru i dlatego jest wolnym kontenerem.
@Onoki: tez tak kiedys myslalem, ale chodzi o to ze vector miesci sie w cache, a to znacznie przyspiesza operacje. Poszperaj, w sieci jest sporo porownan ; ).
std::thread jest niekopiowalny, dlatego musisz uzyc r-value reference, ktora obsluguje emplace_back. W C++11 pojawilo sie move semantics, poczytaj jesli nie slyszales o tym.
push_back bierze universal reference na typ, jaki podales w wektorze, co w praktyce zazwyczaj oznacza, ze najpierw musisz wywolac konstruktor obiektu, potem zrobic
@Onoki: I tak jak koledzy mowili, std::vector jest prawie zawsze lepszym wyborem niz std::list, wlasnie dzieki tej gwarancji, ze elementy sa rozlozone w jednym kawalku pamieci, a nie po niej porozrzucane. Do obejrzenia: http://channel9.msdn.com/Events/Build/2014/2-661
@Onoki najlepiej będzie jak zaimplementujesz jakąś wymianę komunikatów między wątkami i zabijesz je w inteligentny sposób wysyłając rozkaz "quit", inaczej będziesz miał wycieki pamięci i zasobów - w najlepszym wypadku (wyobraź sobie, ƶe zabijasz wątek w momencie gdy trzyma on mutexa do jakiegoś globalnego zasobu).
Na pewne zadanie obliczeniowe przewidziane jest X czasu. Jeżeli się uda je rozwiązać to w porządku, a jeżeli nie to trudno - grunt, żeby nie przekroczyć czasu. Chciałbym rozwiązać wiele takich zadań, każde w osobnym wątku. Mam już coś takiego:
list threads;for (problem : problems) {____threads.push_back(solve(problem));}for (thread : threads) {____thread.join();}I to ścierwo działa, bardzo ładnie działa, ale oczywiście skończy jak skończy i zwraca wszystkie rozwiązania (są one wkładane do kontenera - monitora). Wie ktoś jak inteligentnie zmodyfikować to rozwiązanie tak, żeby przestrzegało ograniczeń czasowych? Podejrzewam, że jest to dość typowy przypadek dlatego nie chce wymyślać koła na nowo.
EDIT: Czas rozwiązania problemu bardzo się różni dla poszczególnych przypadków dlatego zawsze mam pewność, że przy racjonalnym czasie część zdąży się rozwiązać, a część nie.
#programowanie #cpp #cpp11
To jak inaczej?
Co do listy, vector jest szybszy prawie w kazdym wypadku, zeby go zbudowac zrob tak:
vector
@losiul: To ciekawe. Byłem przekonany, że lista jest zbudowana tak, że każdy poprzednik zawiera wskaźnik na następnik (i być może odwrotnie), a elementy mogą sobie być rozrzucone po pamięci. Wektor natomiast musi być przebudowany (skopiowany w inne miejsce) po każdej zmianie rozmiaru i dlatego jest wolnym kontenerem.
Czym się różni emplaceback() od pushback()?
Jakbyś miał jakieś profesjonalne porównanie
std::thread jest niekopiowalny, dlatego musisz uzyc r-value reference, ktora obsluguje emplace_back. W C++11 pojawilo sie move semantics, poczytaj jesli nie slyszales o tym.
@Onoki:
push_backbierze universal reference na typ, jaki podales w wektorze, co w praktyce zazwyczaj oznacza, ze najpierw musisz wywolac konstruktor obiektu, potem zrobic