tbb::parallel_for нехватка памяти на машине с 80 ядрами

Я пытаюсь использовать tbb::parallel_for на машине со 160 параллельными потоками (8 Intel E7-8870) и 0,5 ТБ памяти. Это текущая система Ubuntu с ядром 3.2.0-35-generic #55-Ubuntu SMP. TBB из пакета libtbb2 версии 4.0+r233-1

Даже с очень простой задачей у меня заканчиваются ресурсы, либо «bad_alloc», либо «ресурс thread_monitor временно недоступен». Я свел это к очень простому тесту:

#include <vector>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include "tbb/tbb.h"
#include "tbb/task_scheduler_init.h"
using namespace tbb;

class Worker
{
  std::vector<double>& dst;
 public:
  Worker(std::vector<double>& dst)
    : dst(dst)
    {}

  void operator()(const blocked_range<size_t>& r ) const
  {
    for (size_t i=r.begin(); i!=r.end(); ++i)
      dst[i] = std::sin(i);
  }
};

int main(int argc, char** argv)
{
  unsigned int n = 10000000;
  unsigned int p = task_scheduler_init::default_num_threads();

  std::cout << "Vector length: " << n << std::endl
            << "Processes    : " << p << std::endl;

  const size_t grain_size = n/p;
  std::vector<double> src(n);

  std::cerr << "Starting loop" << std::endl;
  parallel_for(blocked_range<size_t>(0, n, grain_size), RandWorker(src));
  std::cerr << "Loop finished" << std::endl;
}

Типичный вывод

Vector length: 10000000
Processes    : 160
Starting loop
thread_monitor Resource temporarily unavailable
thread_monitor Resource temporarily unavailable
thread_monitor Resource temporarily unavailable

Ошибки появляются случайным образом и тем чаще, чем больше n. Значение в 10 миллионов здесь — это точка, где они случаются довольно регулярно. Тем не менее, учитывая характеристики машины, это далеко не должно исчерпать память (использую для этих тестов только ее).

Размер зерна был введен после того, как tbb создал слишком много экземпляров Worker, что привело к сбою для еще меньшего n.

Кто-нибудь может посоветовать, как настроить tbb для обработки большого количества потоков?


person Guido Kanschat    schedule 12.02.2013    source источник
comment
Вы компилируете программу для 64-битной версии и используете соответствующую версию TBB? Воспроизводится ли проблема, если вы берете последние двоичные файлы TBB с threadingbuildingblocks.org? Ваш класс называется Worker, но в parallel_for вы используете RandWorker; это просто потому, что вы почистили код перед публикацией и забыли переименовать в одном или другом месте?   -  person Alexey Kukanov    schedule 14.02.2013
comment
Алексей, конфликт названий классов действительно произошел из-за уборки. Я только что перекомпилировал после удаления «Rand», утвердил его в 64-битном режиме и использовал последние двоичные файлы. Я вижу два изменения: во-первых, программа работает без сбоев чаще. Во-вторых, сообщение об ошибке, если это не так, более явное: thread_monitor Ресурс временно недоступен в pthread_create   -  person Guido Kanschat    schedule 14.02.2013
comment
В сообщении в основном говорится, что TBB не может создать достаточно потоков; Ресурс временно недоступен — это то, о чем сообщает strerror() по коду ошибки, возвращенному pthread_create(). Я бы рекомендовал написать простой тест, который не использует TBB и вообще ничего не делает, а просто создает столько потоков, сколько может. Также попробуйте изменить размер стека (через атрибуты потока). По умолчанию TBB запрашивает стек 4M для каждого потока; может быть, в вашем случае будет достаточно меньшего значения?   -  person Alexey Kukanov    schedule 14.02.2013
comment
С помощью pthread_create() я могу создать более 600 потоков, где размер стека каждого из них равен значению по умолчанию 8M. Я убедился, что каждый поток занят достаточно долго, поэтому первые не уничтожаются до того, как вступят последние.   -  person Guido Kanschat    schedule 20.02.2013
comment
К сожалению, мы не можем воспроизвести проблему на наших (хотя и меньших по размеру) машинах; например на 64-ядерном сервере TBB отлично работает при инициализации для использования нескольких сотен потоков в режиме сверхподписки. Может глупый вопрос, но вы обязательно компилируете программу под 64 бит, чтобы не ограничивалась 4G на все подряд?   -  person Alexey Kukanov    schedule 21.02.2013
comment
Алексей, проверил. Да, это 64 бит.   -  person Guido Kanschat    schedule 25.02.2013
comment
Извините, что дважды спрашивал о 64-битности - забыл, что уже спрашивал. Обычно вам не нужно ничего делать только из-за размера машины; это должно просто работать. Для дальнейшего устранения неполадок я думаю, что форум TBB мог бы быть лучшим местом.   -  person Alexey Kukanov    schedule 26.02.2013
comment
Стыдно, но ты был на правильном пути. В моей учетной записи был ulimit, который был установлен для другого компьютера. 6 ГБ. Я только что запустил ту же программу с длиной вектора 1G и 1000 потоков. Спасибо за помощь и извините, что не нашли это раньше!   -  person Guido Kanschat    schedule 27.02.2013


Ответы (1)


Подводя итоги обсуждения в комментариях в ответе:

Сообщение «Ресурс thread_monitor временно недоступен в pthread_create» в основном говорит о том, что TBB не может создать достаточное количество потоков; «Ресурс временно недоступен» — это то, что сообщает strerror() по коду ошибки, возвращенному pthread_create(). Одной из возможных причин этой ошибки является недостаток памяти для выделения стека для нового потока. По умолчанию TBB запрашивает 4M стека для рабочего потока; при необходимости это значение можно изменить с помощью параметра конструктора tbb::task_scheduler_init.

В данном конкретном случае, как сообщил Гвидо Каншат, проблема была вызвана случайно установленным ulimit, который ограничил память, доступную для процесса.

person Alexey Kukanov    schedule 03.10.2014