Hi
Достался мне код на доработку. Основная часть выглядит очень просто
while (need_run) {
char * data = getData(); // получить данные с устройства
char * pr_data = processData(data); // обработка
sendData(pr_data); // по сети отправить потребителю.
}
getData — получает данные с устройства, обычно выполняется за постоянное время, порядка 40 мс. processData — от 5 до 100 мс, но обычно также в районе 40-50мс. ( в зависимости от данных). data — несколько мегабайт, pr_data — пара десяток килобайт. По факту, data — глобальный массив. sendData выполняется быстро.
Так как getData и processData абсолютно независимы, захотелось запустить их в отдельных потоках, тем самым поднять в раза полтора скорость. Родился такой код.
#include "stdafx.h"
#include <system_error>
#include <iostream>
#include <windows.h>
#include <process.h>
const int MSIZE = 1024*1024 * 16;
// два буфера, применяются по очереди
char shareData1[MSIZE];
char shareData2[MSIZE];
uintptr_t thr; // хендл потока для получения данных
HANDLE hEvent1, hEvent2; // для двух event'ов
volatile bool run = true; // для остановки потока
char * thrData = NULL; // адрес одного из буферов, куда поток будет вставлять свои данные
// процедура потока
void thrProc(void* args) {
while (run) {
//код, симулирующий получение данных
for (int i = 0; i < MSIZE; i++)
thrData[i] = i % 256;
//signal1
SetEvent(hEvent1);
// wait2
WaitForSingleObject( hEvent2, INFINITE );
}
}
// запуск потока получения данных
void startThread() {
hEvent1 = CreateEvent( NULL, FALSE, TRUE, NULL );
hEvent2 = CreateEvent( NULL, FALSE, FALSE, NULL );
thrData = shareData1;
thr = _beginthread(thrProc, 0, NULL);
}
// функция получения данных
char * getDataNew()
{
// если запросили данные первый раз - запускаем поток
if (thr == NULL) {
startThread();
}
// wait 1
WaitForSingleObject( hEvent1, INFINITE );
// меняем буфера местами
char * data = thrData;
thrData = (thrData == shareData2)?shareData1:shareData2;
// signal 2
SetEvent( hEvent2 );
return data;
}
// функция обработки данных
int processData( char * data )
{
int s = 0;
// симулируем обработку данных
for (int i = 0; i < MSIZE; i++)
s += data[i]; // то, что здесь переполнение, нас мало интересует
return s;
}
// остановка потока получения данных
void stopThread()
{
run = false;
SetEvent(hEvent2); // for stop
WaitForSingleObject( (HANDLE)thr, INFINITE );
}
int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 0; i < 100; i++) { // 100 для приличия, не делать же бесконечный цикл
char * data = getDataNew();
processData(data);
}
stopThread();
return 0;
}
Данный код тестировался примитивным профайлером и показал некоторое ускорение. Правда если уменьшать время получения/обработки данных (параметр MSIZE), то event'ы съедают всю производительность
Покритикуйте пожалуйста. Может можно посмотреть где то на более красивое решение. Цикл в main хочется оставить без изменений (иначе нужно будет много переделывать).