Назначение и управление конкретными потоками в условиях ограничений

Простите меня за то, что я не являюсь экспертом в многопоточности, и мне нужна помощь. Итак, просто некоторые данные, прежде чем я перейду к своему вопросу:

Предварительные знания

  • Разработка кода C++ на Jetson TK1
  • Jetson имеет 4 ядра процессора (четырехъядерный процессор ARMv7)
  • Из того, что я исследовал, каждое ядро ​​​​может использовать один поток (4 ядра -> 4 потока).
  • Я запускаю приложение компьютерного зрения, которое использует OpenCV.
  • Захват кадров с веб-камеры, а также захват кадров из видеофайла

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

int HALT=0;

//Both func1 and func2 can be ran parallel for a short period of time
//but both must finish before moving to the next captured webcam frame
void func1(*STUFF){
    //Processes some stuff
}
void func2(*STUFF){
    //Processes similar stuff
}

void displayVideo(*STUFF){
    while(PLAYBACK!=DONE){
        *reads video from file and uses imshow to display the video*
        *delay to match framerate*
    }
    HALT=1;
}
main{
    //To open these I am using OpenCVs VideoCapture class
    *OPEN VIDEO FILE* 
    *OPEN WEBCAM STREAM*
    thread play(displayVideo, &STUFF);
    play.detach();
    while(HALT!=1){
        *Grab frame from webcam*
        //Process frame
        thread A(func1,&STUFF);
        thread B(func2,&STUFF);
        A.join();
        *Initialize some variables and do some other stuff*
        B.join();
        *Do some processing... more than what is between A.join and B.join*
        *Possibly display webcam frame using imshow*
        *Wait for user input to watch for terminating character*
    }
    //This while loop runs for about a minute or two so thread A and thread
    //B are being constructed many times.
}

Вопрос(ы) Итак, я хотел бы знать, есть ли способ указать, какое ядро/поток я буду использовать при создании нового потока. Я боюсь, что когда я снова и снова создаю потоки A и B, они перескакивают на разные потоки и снижают скорость моей системы и/или чтение видео. Хотя это опасение не совсем оправдано, я вижу очень странное поведение на четырех ядрах при запуске кода. Обычно я всегда вижу одно ядро, работающее на 40-60%, которое, как я полагаю, является либо основным потоком, либо потоком воспроизведения. А вот что касается остальных ядер, то вычислительная нагрузка очень скачкообразная. Кроме того, во время игры в приложении я вижу, как два ядра загружаются с 60% до 100%, но эти два ядра не остаются постоянными. Это может быть первое, второе, третье или даже четвертое ядро, и тогда они сильно снизятся, обычно примерно до 20-> 40%. Иногда я вижу, как только 1 ядро ​​падает до 0% и остается таким, что кажется другим циклом цикла while (т. е. захват кадра, процесс, поток A, поток B, повтор). Затем я увижу, что все четыре из них снова активны, что является более ожидаемым поведением.

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


person John-Michael Burke    schedule 12.05.2015    source источник
comment
Условие гонки: вы получаете доступ к HALT из main и из потока play`. Поэтому программа выдает неопределенное поведение. У вас есть c++11?   -  person nwp    schedule 12.05.2015
comment
Хорошо, это имеет смысл. Да, я использую С++ 11. Не могли бы вы порекомендовать лучший подход к этому? Идея состоит в том, что если во время воспроизведения в потоке воспроизведения будет нажата клавиша ESC, воспроизведение прекратится... возврат к основному... тогда цикл while в основном не будет продолжаться.   -  person John-Michael Burke    schedule 12.05.2015
comment
C++11 делает это немного проще. Используйте std::atomic<int> Halt; (которую вам нужно вручную установить на 0), чтобы исправить это состояние гонки. То же самое касается PLAYBACK. Если STUFF не const, у вас есть еще одна гонка. Создание и уничтожение потоков недешево, делать это в цикле излишне медленно. Вместо этого рассмотрите возможность использования пула потоков. Другая возможность - использовать std::async, который может сделать это за вас. Вы должны убедиться, что у вас нет состояния гонки, которое требует медленной синхронизации. Однопоточный может быть быстрее и проще.   -  person nwp    schedule 12.05.2015