2016-02-29 5 views
0

Я довольно новичок в std :: thread, и я быстро понял, что их создание довольно дорого по крайней мере на моем компьютере под управлением W7. Поэтому я решил создать свои темы и отправлять задания на него с помощью этого куска образца кода: http://en.cppreference.com/w/cpp/thread/condition_variableОтправка заданий на std :: thread

Моего кода не работает так не аварий, однако я не заметил большой прирост производительности, так что я измерил разницу между временем работы (см. WaitUntilJobFinished()) Я заметил, что в некоторых случаях разница во времени составляла более 2 миллисекунд

Кто-нибудь видит что-то не так с кодом?

Код:

class CJobParameters 
{ 
public: 
}; 

typedef void (*CJobFunc)(const CJobParameters *); 

class CThread 
{ 
public: 
    void Start(); 
    void WaitUntilJobDone(); 
    void StartJob(CJobFunc inJobFunc, const CJobParameters * inJobParameters); 

    std::thread m_stdThread; 

    CJobFunc    m_jobFunc  = nullptr; 
    const CJobParameters * m_jobParameters = nullptr; 
    //std::atomic<bool>  m_jobDone  = true; 
    std::mutex    m_mutex; 
    std::condition_variable m_cv; 

    __int64 m_jobDoneAt = 0; 
    __int64 m_threadJoinedAt = 0; 
    __int64 m_lostTime = 0; 
}; 

class CThreads 
{ 
public: 
    static void Start(); 
    static CThread threadArray[ JOB_COUNT ]; 
}; 


void ThreadMain(CThread * inThread) 
{ 
    while (true) 
    { 
     std::unique_lock<std::mutex> lk(inThread->m_mutex); 
     inThread->m_cv.wait(lk, [ inThread ]{return inThread->m_jobParameters != nullptr;}); 
     if (inThread->m_jobFunc) 
     { 
      (*inThread->m_jobFunc)(inThread->m_jobParameters); 
      inThread->m_jobFunc = nullptr; 
      inThread->m_jobParameters = nullptr; 
      inThread->m_jobDoneAt = COSToolbox::QuerySystemTime2(); 
     } 
     lk.unlock(); 
     inThread->m_cv.notify_one(); 
     std::this_thread::sleep_for(std::chrono::nanoseconds(0)); 
    } 
} 

void CThread::StartJob(CJobFunc inJobFunc, const CJobParameters * inJobParameters) 
{ 
    std::lock_guard<std::mutex> lk(m_mutex); 
    m_jobFunc   = inJobFunc; 
    m_jobParameters  = inJobParameters; 
    m_cv.notify_one(); 
} 

void CThread::Start() 
{ 
    m_stdThread = std::thread(ThreadMain, this); 
} 

void CThread::WaitUntilJobDone() 
{ 
    std::unique_lock<std::mutex> lk(m_mutex); 
    m_cv.wait(lk, [ this ]{return this->m_jobParameters == nullptr;}); 

    m_threadJoinedAt = COSToolbox::QuerySystemTime2(); 
    m_lostTime = m_threadJoinedAt - m_jobDoneAt; 
    LOG_INFO("Thread joined with %f ms lost", (Float32)m_lostTime/1000); 
} 


CThread CThreads::threadArray[ JOB_COUNT ]; 
void CThreads::Start() 
{ 
    for (Int32 i = 0; i < JOB_COUNT; ++i) 
    { 
     threadArray[i].Start(); 
    } 
} 

void MyJobFunc(const CJobParameters * jobParameters) 
{ 
    // do job here 
} 
void main() 
{ 
    CThreads::Start(); 
    while(true) 
    { 
     CJobParameters jobParametersArray[ JOB_COUNT ]; 
     for (Int32 i = 0; i < JOB_COUNT; ++i) 
     { 
      CThread & thread = CThreads::threadArray[ i ]; 
      CJobParameters& jobParameters = jobParametersArray[ i ]; 
      jobParameters.m_ // Fill in params 
      thread.StartJob(&MyJobFunc, &jobParameters); 
     } 
     for (Int32 i = 0; i < JOB_COUNT; ++i) 
     { 
      CThread & thread = CThreads::threadArray[ i ]; 
      // Prints 2 ms sometimes whith i = 0 
      thread.WaitUntilJobDone(); 
     } 
    } 
} 

ответ

0

Две вещи:

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

std::this_thread::sleep_for(std::chrono::nanoseconds(0)); 

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

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

+0

Спасибо за ответ. Я вернусь к вам, как только найду время попробовать. – OeilDeLance

+0

Итак, очевидно, что мои 2 мс пришли из моей собственной ошибки. теперь я сократил время до 0,2 мс максимум. Который много. Я также удалил урожай, но это ничего не меняет. – OeilDeLance

+0

Я не уверен, что понимаю, зачем мне нужны две условные переменные. Этот пример реализует его только с одним ожиданием двух разных bools: http://en.cppreference.com/w/cpp/thread/condition_variable. Я думаю, если бы это был один bool, это не имело бы никакого значения. – OeilDeLance