Necesito pasar a un hilo por valor un bloque de flotantes que son un puntero devuelto por una biblioteca de terceros. Algo como esto:

void TestThread(std::vector<float> data)
{
  std::cout << data.size();
}

void Thready ()
{
  vector<thread> threads(10);  // this actually varies at runtime.

  for (int i = 0; i < 10; i++)
  {
      float* data = HeapsOfFloats();
      int numberOfFloats = NumberOfFloats();
      std::vector<float> dataVector(data, data + numberOfFloats);
      threads[i] = std::thread::thread([&]{TestThread(dataVector)});
  }

  for (int t = 0; t < 10; t++) threads[t].join();
}

Después de 1 n iteraciones del ciclo, mi programa falla.

1
empty 14 ene. 2017 a las 02:13
O se bloquea porque estás enviando mensajes no deseados
 – 
deW1
14 ene. 2017 a las 02:16
porque los flotantes no son tipos integrales, por lo que todavía hay punteros escondidos en esto. ¿Cómo es eso?
 – 
Algirdas Preidžius
14 ene. 2017 a las 02:19
Además del comentario muy verdadero de Oleg acerca de pasar dataVector por referencia a su lambda (considere usar [vec = std::move(dataVector)] { TestThread(vec) } para mover limpiamente los datos al cierre), todo se ve bien desde aquí y sospecho que su falla está en algún lugar de HeapsOfFloats o NumberOfFloats. No entiendo su comentario acerca de que los flotadores no son tipos integrales ni punteros.
 – 
zneak
14 ene. 2017 a las 02:48
1
Integral significa que solo ese tipo es entero. Ni más ni menos. Los números de coma flotante también se almacenan como bloques de memoria normales.
 – 
Logman
14 ene. 2017 a las 03:05
Se eliminaron las referencias integrales en OP y en los comentarios.
 – 
Kevin
14 ene. 2017 a las 03:28

1 respuesta

La mejor respuesta

Editar: está capturando un vector por referencia (al objeto) que se destruirá después de que finalice la iteración de su bucle, si tiene suerte y la llamada a la función dentro de lambda ya lo ha copiado; funciona, si tiene mala suerte, no hay nada que copiar y tienes un accidente. Dado que desea utilizar una copia de todos modos, le sugiero que la capture mediante una copia en lambda y luego la pase por ref:

void TestThread(const std::vector<float>& data)
{
  std::cout << data.size();
}

void Thready ()
{
  vector<thread> threads(10);  // this actually varies at runtime.

  for (int i = 0; i < 10; i++)
  {
      float* data = HeapsOfFloats();
      int numberOfFloats = NumberOfFloats();
      std::vector<float> dataVector(data, data + numberOfFloats);
      threads[i] = std::thread::thread([dataVector]{TestThread(dataVector)});
  }

  for (int t = 0; t < 10; t++) threads[t].join();
}

Bono: su código (y el mío) incurre en dos copias de datos flotantes, pero podría salirse con la suya con al menos una copia menos si puede escribir en c ++ 14:

...
 threads[i] = std::thread::thread([dataVector(std::move(dataVector))]{TestThread(dataVector)});
...

Para soluciones anteriores a C ++ 14, busque aquí o envuelva su vector en algo como shared_ptr que sería más barato de copiar


No creo que haya nada de malo en la forma en que agarras tus flotadores (si solo generas demasiados hilos).

Sin embargo, creo que su problema está en otra parte: está destruyendo subprocesos en cada iteración, pero tienen que separarse o unirse manualmente para evitar la terminación, a veces tiene suerte y se ejecutan hasta la terminación antes de que finalice su ciclo de bucle, a veces, no es así. Solo considere separe al final de la iteración si no le importa sobre ellos y no planeo usar identificadores de hilo más adelante

4
Community 23 may. 2017 a las 15:24
Ver Editar, probablemente sea útil
 – 
Oleg Bogdanov
14 ene. 2017 a las 02:39