c++ - Why do my threads sometimes "stutter"? -


i trying write multithreaded code read daq device , render captured signal @ same time:

std::atomic <bool> rendering (false); auto render = [&rendering, &display, &signal] (void)     {         while (not rendering)             {std::this_thread::yield ();};         {display.draw (signal);}             while (display.rendering ()); // returns false when user quits         rendering = false;     }; auto capture = [&rendering, &daq] (void)     {         (int = daq.read_frequency (); --> 0;)             daq.record (); // fill buffer before displaying signal         rendering = true;         {daq.record ();}              while (rendering);         daq.stop ();     }; std::thread rendering_thread (render); std::thread capturing_thread (capture);  rendering_thread.join (); capturing_thread.join (); 

sometimes work fine, bad stuttering. had render () , capture () print line upon each loop iteration, , colored lines such red render () , blue capture ():

thread execution vs time

the left plot smooth run, right plot run stuttering.

i had equivalent program in c using openmp , performance smooth:

int status = 0; #pragma omp parallel num_threads(2) private(tid) shared(status) /* read , draw */ {  tid = omp_get_thread_num ();  /* draw */ if (tid 0) {      int finished = 0;      while (not finished) {          #pragma omp critical          /* job status */ {              finished = status;          }          finished = renderdisplay ();      }      #pragma omp critical      /* terminate display */ {          cvdestroyallwindows();      }      #pragma omp atomic      status ++;      #pragma omp flush(status)  }  /* read */ if (tid 1) {      int finished = 0;      while (not finished) {          #pragma omp critical          /* job status */ {              finished = status;          }          capturesignal ();      }  }  #pragma omp barrier } 

at least, both c , c++11 versions look equivalent me, can't figure out why stuttering happening in c++11 version.

i can't post sscce because daq.* routines depend on ni daq library, may worth noting daq.record () blocks until physical device finished reading, , ni daq lib spawns several threads when starts.

i've tried implementing atomic flags in various configurations , changing function call orders , nothing seems have effect.

what going on here, , how can control it?

update: increasing sampling rate of daq alleviates problem, leads me suspect have fact daq.record () blocking call.

as people in comments have mentioned don't have control of scheduling. can more turn away spin locks , use conditions. force put render thread sleep if went fast , processed data capture thread has produced. can @ this example 1 iteration. in case every time more data becomes available capture thread, need call notify_one(). can use version of wait takes 1 parameter case.

so code become this

std::mutex mutex; std::condition_variable condition; std::atomic <bool> rendering (false); auto render = [&rendering, &display, &signal] (void)     {         // while loop not needed anymore because         // wait signal before doing drawing         while (not rendering)             {std::this_thread::yield ();};         // first lock. destructor unlock         std::unique_lock<std::mutex> lock(mutex);         {                // wait until have been signaled                condition.wait(lock);                // maybe check display.rendering() , exit (depending on req.)                // process data available                display.draw (signal);            } while (display.rendering ()); // returns false when user quits         rendering = false;     }; auto capture = [&rendering, &daq] (void)     {         (int = daq.read_frequency (); --> 0;)             daq.record (); // fill buffer before displaying signal         rendering = true;         condition.notify_one();         // special note; can call notify_one() here         // mutex lock not acquired.         {daq.record (); condition.notify_one();}              while (rendering);         daq.stop ();         // signal 1 more time render thread have         // been in "wait()" call         condition.notify_one();     }; std::thread rendering_thread (render); std::thread capturing_thread (capture);  rendering_thread.join (); capturing_thread.join (); 

doing way consume less cpu resources, render thread go sleep when there no data process.


Comments

Popular posts from this blog

android - Get AccessToken using signpost OAuth without opening a browser (Two legged Oauth) -

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: mockito -

google shop client API returns 400 bad request error while adding an item -