Многопоточность с использованием библиотеки Boost - PullRequest
4 голосов
/ 05 декабря 2008

Желание одновременно вызывать функцию несколько раз. Я хочу использовать потоки для вызова функции, которая будет в полной мере использовать возможности машины. Это 8-ядерная машина, и мое требование - использовать процессор от 10% до 100% и более.

Мое требование - использовать класс повышения. Есть ли способ, которым я могу сделать это, используя поток поддержки или библиотеку потоков? Или какой-то другой способ сделать это?

Кроме того, если мне придется каждый раз вызывать несколько функций с разными параметрами (с отдельными потоками), каков наилучший способ сделать это? [используя повышение или не используя повышение] и как?

#include <iostream>
#include <fstream>
#include <string.h>
#include <time.h>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>

using namespace std;
using boost::mutex;
using boost::thread;

int threadedAPI1( );
int threadedAPI2( );
int threadedAPI3( );
int threadedAPI4( );

int threadedAPI1( ) {
    cout << "Thread0" << endl;
}


int threadedAPI2( ) {
    cout << "Thread1" << endl;
}

int threadedAPI3( ) {
    cout << "Thread2" << endl;
}

int threadedAPI4( ) {
    cout << "Thread3" << endl;
}

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

    boost::threadpool::thread_pool<> threads(4);
    // start a new thread that calls the "threadLockedAPI" function
    threads.schedule(boost::bind(&threadedAPI1,0));
    threads.schedule(boost::bind(&threadedAPI2,1));
    threads.schedule(boost::bind(&threadedAPI3,2));
    threads.schedule(boost::bind(&threadedAPI4,3));
    // wait for the thread to finish
    threads.wait();

    return 0;
}

Выше не работает, и я не уверен, почему? : - (

Ответы [ 3 ]

6 голосов
/ 05 декабря 2008

Я предлагаю вам ознакомиться с документацией по функциям, которые вы используете. Из вашего комментария в ответе Джеймса Хопкина кажется, что вы не знаете, что делает boost :: bind, а просто скопировали код.

boost :: bind принимает функцию (назовите ее f) и, необязательно, несколько параметров и возвращает функцию, которая при вызове вызывает f с указанными параметрами.

То есть boost::bind(threadedAPI1, 0)() (создание функции, которая не принимает аргументов и вызывает threadadedAPI1 () с аргументом 0, а затем ее вызов) эквивалентно threadedAPI1(0).

Поскольку ваши функции threadadedAPI на самом деле не принимают никаких параметров, вы не можете передавать им аргументы. Это просто фундаментальный C ++. Вы не можете вызвать threadedAPI1(0), но только threadedAPI1(), и все же, когда вы вызываете функцию, вы пытаетесь (через boost :: bind) передать целое число 0 в качестве аргумента.

Итак, простой ответ на ваш вопрос - просто определить threadadedAPI1 следующим образом:

int threadedAPI1(int i);

Однако, один из способов избежать вызовов boost :: bind - это вызвать функтор вместо свободной функции при запуске потока. Объявите класс примерно так:

struct threadedAPI {
  threadedAPI(int i) : i(i) {} // A constructor taking the arguments you wish to pass to the thread, and saves them in the class instance.

  void operator()() { // The () operator is the function that is actually called when the thread starts, and because it is just a regular class member function, it can see the 'i' variable initialized by the constructor
    cout << "Thread" << i << endl; // No need to create 4 identical functions. We can just reuse this one, and pass a different `i` each time we call it.
  }
private:
  int i;
};

Наконец, в зависимости от того, что вам нужно, простые потоки могут лучше подходить, чем пул потоков. В общем случае пул потоков запускает только ограниченное количество потоков, поэтому он может ставить в очередь некоторые задачи до тех пор, пока не завершится выполнение одного из потоков. Он в основном предназначен для случаев, когда у вас много краткосрочных задач.

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

4 голосов
/ 05 декабря 2008

Вы связываете параметры с функциями, которые не принимают параметры:

int threadedAPI1( );

boost::bind(&threadedAPI1,0)

Просто передайте функцию напрямую, если нет параметров:

threads.schedule(&threadedAPI1)
3 голосов
/ 05 декабря 2008

Если вы заинтересованы в эффективном использовании вашего процессора, то вы можете рассмотреть возможность создания потоковых блоков intels http://www.intel.com/cd/software/products/asmo-na/eng/294797.htm. Я полагаю, что он разработан специально для использования многоядерных процессоров, в то время как потоки надстройки оставляют контроль над пользователем (т.е. TBB будет работать по-другому на четырехъядерном процессоре по сравнению с двухъядерным).

Что касается вашего кода, вы привязываете функции, которые не принимают параметры к параметру. Зачем? Вы также можете проверить код возврата из расписания.

...