简体   繁体   中英

How to make a thread wait for a condition to perform an operation without it using too much CPU time?

I've been trying to use threads in a matrix operation to make it faster for large matrixes (1000x1000). I've had some sucess so far with the below code. With significant speed improvements in comparision to using a single thread.

void updateG(Matrix &u, Matrix &g, int n, int bgx, int tamx, int tamy) 
{
int i, j;

for (i = bgx; i < tamx; i += n)
 {
    for (j = 0; j < tamy; j++)
    {
        g(i,j, g(i,j)+ dt * 0.5 * (u(i,j) - (g(i,j) * y)));
    }
 }
}
void updateGt(Matrix &u, Matrix &g, int tam)strong text
{
 int i;
 const int n = NT;
 std::thread array[n];
 for (int i = 0; i < n; i++)
 {
    array[i] = std::thread(updateG, std::ref(u), std::ref(g), n, i, tam, tam);
 }
 joinAll(array, n);
}

However, I need to call this operation several times in the main code, and every time this happens, I must initialize the thread array again, creating new threads and wasting a lot of time (according to what I've read online those are expensive). So, I've developed an alternative solution to create and initialize the thread array only once, and use the same threads to perform the matrix operations every time the function is called. Using some flag variables so the thread only performs the operation when it has to. Like in the following code:

  void updateG(int bgx,int tam)
  {
    while (!flaguGkill[bgx]) {
        if (flaguG[bgx]) {
            int i, j;

            for (i = bgx; i < tam; i += NT)
            {
                for (j = 0; j < tam; j++)
                {
                    g->operator()(i, j, g->operator()(i, j) + dt * 0.5 * (u->operator()(i, j) - (g->operator()(i, j) * y)));
                }
            }
            flaguG[bgx] = false;

        }
    }
  }

 void updateGt()
 {
    
    for (int k = 0; k < NT; k++)
    {
        flaguG[k] = true;

    }

    for (int i = 0; i < NT; i++)
    {
        while(flaguG[i]);
    }
   }

My problem is. This solution, that's supposed to be faster, is much slower than the first one, by a large margin. In my complete code, I have 2 functions like this updateGt and updateXt, and I'm using 4 threads for each, I believe the problem is that while the function is supposed to be idle waiting, it is instead using a lot of CPU time only to keep checking on the codition. Anyone knows if that is really the case, and if so, how could I fix it?

The problem here is called busy waiting . As mentioned in comments you'll want to use std::condition_variable , like this:

std::mutex mutex;
std::condition_variable cv;   

while (!flaguGkill[bgx]) {
    {
    unique_lock<mutex> lock(mutex); // aquire mutex lock as required by condition variable
    cv.wait(lock, [this]{return flaguG[bgx];}); // thread will suspend here and release the lock if the expression does not return true
    } 

    int i, j;
    
    for (i = bgx; i < tam; i += NT)
    {
        for (j = 0; j < tam; j++)
        {
            g->operator()(i, j, g->operator()(i, j) + dt * 0.5 * (u->operator()(i, j) - (g->operator()(i, j) * y)));
        }
    }
    flaguG[bgx] = false;
    
}

Note: the section [this] { return flaguG[bgx];} , you may need to alter the capture paramaters (the bit in the [] ) depending on the scope of those variables

Where you set this to be true, you then need to call

for (int k = 0; k < NT; k++)
{
    flaguG[k] = true;
    cv.notify_one();
}

// you can then use another condition variable here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM