C ++ темы. Почему всегда выполняет последний поток? - PullRequest
2 голосов
/ 02 мая 2020

Почему только последние потоки выполняются каждый раз? Я пытаюсь разделить сетку на N рабочих, половина сетки всегда недоступна, а другая часть всегда обрабатывается 1 последним созданным потоком. Должен ли я использовать массив вместо вектора? Замки также не помогают решить эту проблему.

#include <iostream>
#include <unistd.h>
#include <vector>

#include <stdio.h>
#include <cstring>

#include <future>
#include <thread> 
#include <pthread.h>

#include <mutex>

using namespace std;

std::mutex m;

int main(int argc, char * argv[]) {

  int iterations = atoi(argv[1]), workers = atoi(argv[2]), x = atoi(argv[3]), y = atoi(argv[4]);

  vector<vector<int> > grid( x , vector<int> (y, 0));
  std::vector<thread> threads(workers);

  int start, end, lastworker, nwork;

  int chunkSize = y/workers;

  for(int t = 0; t < workers; t++){

    start = t * chunkSize;
    end = start + chunkSize;

    nwork = t;

    lastworker = workers - 1;

    if(lastworker == t){
      end = y; nwork = workers - 1;
    }

threads[nwork] = thread([&start, &end, &x, &grid, &t, &nwork, &threads] {

                cout << " ENTER TO THREAD -> " << threads[nwork].get_id() << endl;

    for (int i = start; i < end; ++i)
                {
                    for (int j = 0; j < x; ++j)
                    {
                      grid[i][j] = t;

                    }              
                }

                sleep(2);
        });
cout << threads[nwork].get_id() << endl;

}

for(auto& th : threads){
 th.join();
}

    for (int i = 0; i < y; ++i)
    {
        for (int j = 0; j < x; ++j)
        {
          cout << grid[i][j];

        }
        cout << endl;
    } 

  return(0);
}

Ответы [ 3 ]

0 голосов
/ 02 мая 2020
thread([&start, &end, &x, &grid, &t, &nwork, &threads] {
                                     =======

Лямбда-замыкание, которое выполняется каждым потоком, захватывает ссылку на nwork.

, что означает, что for l oop повторяет и запускает каждый поток, каждый захваченный поток всегда ссылается на current значение nwork, в то время, как это происходит.

Таким образом, внешний l oop, вероятно, быстро завершает создание каждого объекта потока, прежде чем все потоки фактически инициализируются и фактически входят в лямбда-замыкание, и каждое закрытие видит одно и то же значение nwork, поскольку оно захватывается по ссылке , который является последним идентификатором потока.

Вам нужно захватить nwork по значению вместо ссылки.

0 голосов
/ 02 мая 2020

Вы передаете все параметры потока, являющиеся ссылками на лямбду потока. Однако, когда l oop продолжается в основном потоке, переменные параметров потока изменяются, что также приводит к изменению их значений в threads , что портит все ранее созданные потоки.

0 голосов
/ 02 мая 2020
[&start, &end, &x, &grid, &t, &nwork, &threads]

Эта строка является root проблемы. Вы фиксируете все переменные по ссылке, а это не то, что вы хотите сделать.

Как следствие, каждый поток использует одни и те же переменные, что тоже не то, что вам нужно.

Вы должны захватывать только grid и threads по ссылке, остальные переменные должны быть захвачено по значению («скопировано» в лямбду)

[start, end, x, &grid, t, nwork, &threads]

Кроме того, вы получаете доступ к grid неправильно везде: измените grid[i][j] на grid[j][i]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...