Многопоточная Предварительное Выделение Памяти


Мне нужно выяснить, лучший способ справиться с предварительного выделения памяти

Ниже приведен псевдо-код для того, что я делаю сейчас, и это, кажется, работает хорошо.

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

В потоке а мне нужно выделить 300 МБ памяти и ноль это:

Нить:

char* myMemory = new char[10*30*1024*1024];

В потоке б я пошагово вам 10 наборов данных 30 МБ каждый. Как мне получить эти данные, он должен быть записан в память

Поток B:

int index1 = 0;
char* newData = getData(...); // get a pointer to 30 MB of data
memcpy(&myMemory[index1*30*1024*1024], &newData[0], 30*1024*1024];
SetEvent(...) // tell Thread C that I have written new data

// use index i as circular Buffer
if (index1 < 10)
 index1++;
else
 index1 = 0;

В треде С, при записи новых данных, мне нужно получить его и обработать его

Нить C:

int index2 = 0;
char* dataToProcess[] = new char[30*1024*1024];
if (event Fires) // if event in Thread B is set
 memcpy(&dataToProcess[0], &myMemory[index2*30*1024*1024], 30*1024*1024];
 processData(dataToProcess)

// use index i as circular Buffer
if (index2 < 10)
 index2++;
else
 index2 = 0;


1269
1
задан 9 апреля 2011 в 01:04 Источник Поделиться
Комментарии
3 ответа

Я не уверен, как потоки работают, но, похоже, вам нужна дополнительная синхронизация.

Если B и C представляют собой пару, я не вижу индексации выходит из-под контроля, а вы не задумывались о порядке выполнения и перенумерация пишет память? Б процессор может выполнять код запускающий событие перед завершением напишите сайт mymemory, в результате чего в C значение частичные данные. Конечно, это может быть в вашем случае маловероятно или вообще невозможно, но это что-то подумать. Вам может понадобиться памяти или более высокого уровня синхронизации концепции.

В самом деле, почему не использовать очереди сообщений? Или что-то попроще, как кольцевой буфер? (Кстати, буст::circular_buffer нити-безопасный ограниченный буфер, пример очень похож на ваш вопрос.)

Или если бы вы могли прикрепить 30 МБ данных событий, это было бы очень простое решение.

1
ответ дан 9 апреля 2011 в 01:04 Источник Поделиться

Еще один подход я могу думать, может быть это. Избавиться от сайт mymemory в целом. Как только вы получите данные в поток B, выделить память и скопировать эти данные (как вы делаете сейчас). Отправить нити c сообщение о том, что полученные данные. Как только нить c копирует данные в свой внутренний буфер, резьба C может отправить сообщение обратно в поток B, что данные были скопированы. Нить Б потом освободить буфер.

Ваш дизайн выглядит хорошо для меня. Еще один подход можно было бы избежать копирования данных в поток С.

int index2 = 0;
char* dataToProcess;
if (event Fires) // if event in Thread B is set
dataToProcess = &myMemory[index2*30*1024*1024];
processData(dataToProcess)
// Rest of the code

0
ответ дан 9 апреля 2011 в 01:04 Источник Поделиться

можно использовать такой подход (псевдокод);

template < typename T, size_t BlockSize_ >
class t_lockable_array {
public:
static const size_t BlockSize = BlockSize_;
typedef T t_object;

/* ...stuff... */

void copyElements(std::vector& dest, const t_range& range) {
t_lock_scope lock(this->mutex());
/* copy @a range to @a dest here... */
}

/* ...stuff... */

private:
t_mutex d_mutex; /* assumption in this example: lock/unlock is a mutation */
t_object d_object[BlockSize];
};

template < typename T, size_t BlockSize_, size_t BlockCount_ >
class t_partitioned_array {

public:
static const size_t BlockSize = BlockSize_;
static const size_t BlockCount = BlockCount_;
static const size_t ObjectCount = BlockCount * BlockSize;
typedef T t_object;

/* ...stuff... */

t_lockable_array<t_object, BlockSize>& at(const size_t& idx) {
/*
direct access: each partition handles its locking/interface.
alternatively, you could rewrap the lockable array's
interface if you prefer encapsulation here.
*/
return this->d_array[idx];
}

/* ...stuff... */

private:
t_lockable_array<t_object, BlockSize> d_array[BlockCount];
};

тогда просто создайте t_partitioned_array на нить

на нить B:

t_partitioned_array<char,10,ThirtyMB>& array(this->getSharedArray());
std::vector<char>& localBuffer(this->getLocalBuffer());

// the accessed partition will lock itself during read/write
array.at(this->partitionToRead()).copyElements(localBuffer, this->rangeOfMemoryToRead());

this->processData(localBuffer);

0
ответ дан 9 апреля 2011 в 06:04 Источник Поделиться