2015-11-24 2 views
0

Этот вопрос относится к this previous question.boost :: io_service post с использованием лямбда

Я реализовал код, опубликованный там Ричардом Ходжесом. Код, опубликованный для меня, когда я использую g++ (Debian 4.8.4-1) 4.8.4.

Однако реализация является частью библиотеки CUDA, и я застрял с CUDA 6.5, который неофициально поддерживает функции C++ 11.

Когда я использую код Ричард отвечал:

template <class F> 
void submit(F&& f) 
{ 
    std::unique_lock<std::mutex> lock(_cvm); 
    ++ _tasks; 
    lock.unlock(); 
    _io_service.post(
    [this, f = std::forward<F>(f)] 
        { 
         f(); 
         reduce(); 
        }); 
} 

Я получаю сообщение об ошибке: error: expected a "]" со ссылкой на лямбда-линии. Это заставляет меня думать, что заголовок не обрабатывается должным образом. Я пробовал без шаблона, просто передавая ссылку на мой рабочий класс и без пересылки.

void submit(trainer & job) 
{ 
    std::unique_lock<std::mutex> lock(_cvm); 
    ++ _tasks; 
    lock.unlock(); 
    _io_service.post([this,&] 
        { 
         job(); 
         reduce(); 
        }); 
} 

И у меня error: an enclosing-function local variable cannot be referenced in a lambda body unless it is in the capture list.

Так я явно добавил как this и job:

void submit(trainer & job) 
{ 
    std::unique_lock<std::mutex> lock(_cvm); 
    ++ _tasks; 
    lock.unlock(); 
    _io_service.post([this,&job] 
        { 
         job(); 
         reduce(); 
        }); 
} 

В этот момент, я застрял на ошибку:

error: could not convert ‘{{((cuANN::trainer_pool*)this)->cuANN::trainer_pool::_io_service}}’ from ‘<brace-enclosed initializer list>’ to ‘boost::asio::io_service::work’ boost::asio::io_service::work _work { _io_service };

FYI, cuANN::trainer_pool является worker_pool в примере Ричарда, и реализация пула нитей и _io_service является просто членом class trainer_pool:

class trainer_pool 
{ 
public: 
    trainer_pool (unsigned int max_threads); 
    void start(); 
    void wait(); 
    void stop(); 
    void thread_proc(); 
    void reduce(); 
    void submit(trainer & job); 

private: 
    unsigned int _max_threads_; 
    boost::asio::io_service _io_service; 
    boost::asio::io_service::work _work { _io_service }; 
    std::vector<std::thread> _threads; 
    std::condition_variable _cv; 
    std::mutex _cvm; 
    size_t _tasks = 0; 
}; 
  1. Что я делаю неправильно?
  2. Как это сделать, используя std :: bind или boost :: bind вместо использования лямбда?

PS: код на http://ideone.com/g38Z4H - мой скелет для g ++ (который работает). http://ideone.com/d7Nkop сохранен как host.cu также демонстрирует проблему.

nvcc -std=c++11 host.cu -lboost_thread -lboost_system -lpthread -o host

+2

Можете ли вы предоставить короткий полный код (так что мне не нужно копаться, чтобы попытаться угадать, что вы компилируете) вместе с точной командой компиляции, которую вы используете? –

+0

Этот код используется в коде устройства? Если нет, то может быть выделена отдельная компиляция кода хоста и устройства. – havogt

+0

@havogt это нужно запускать только на хосте, но я создаю его как библиотеку. –

ответ

1

Я нашел проблему. NVCC и CUDA отлично работают с лямбдами.

Нарушитель линия в заголовке:

boost::asio::io_service::work _work { _io_service }; 

CUDA 6.5 не нравится список инициализатора. Перемещение его конструктору:

trainer_pool (unsigned int max_threads) 
:_max_threads_(max_threads), _work(_io_service) 
{} 

Кажется, исправили ошибку и код в настоящее время составляет. Огромное спасибо всем, кто помогал.

+0

отличная новость :-) –

2

эта конструкция:

[this, f = std::forward<F>(f)] 

является C++ 14 и не компилировать в C++ 11.

с помощью [this, &] было бы ошибкой, так как нет никакой гарантии, что функция объекта будет существовать (вы захватили его по ссылке)

в C++ 11 считают [this, f] взять копию.

редактировать: просто понял, что работа является изменяемым, поэтому:

void submit(trainer & job) 
{ 
    std::unique_lock<std::mutex> lock(_cvm); 
    ++ _tasks; 
    lock.unlock(); 
    _io_service.post([this,job]()->void mutable 
        { 
         job(); 
         reduce(); 
        }); 
} 
+0

Привет, Ричард, спасибо за ответ. К сожалению, проблема все еще сохраняется, если я копирую ее по значению в лямбда. Я думаю, что это проблема с cuda 6.5/nvcc. Знаете ли вы, как я могу сделать то же самое с помощью bind? –

+0

bind было бы сложным, но вы могли бы просто определить локальную структуру, которая имеет оператор вызова (в основном ручное кодирование лямбда). –

+0

. Вы имеете в виду, что мне нужна оболочка для ссылки как на _io_service, так и на работника потоков? Мне кажется, что у меня нет другого выбора, так как я не могу собрать лямбда. –