У меня есть проект, в котором у меня есть один поток-производитель, который записывает события в буфер, и дополнительный одиночный поток-потребитель, который берет события из буфера. Моя цель — оптимизировать эту штуку для одного двухъядерного компьютера, чтобы добиться максимальной пропускной способности.
В настоящее время я использую простой кольцевой буфер без блокировки (без блокировки возможен, поскольку у меня есть только один поток потребителя и один поток производителя, и поэтому указатели обновляются только одним потоком).
#define BUF_SIZE 32768
struct buf_t { volatile int writepos; volatile void * buffer[BUF_SIZE];
volatile int readpos;) };
void produce (buf_t *b, void * e) {
int next = (b->writepos+1) % BUF_SIZE;
while (b->readpos == next); // queue is full. wait
b->buffer[b->writepos] = e; b->writepos = next;
}
void * consume (buf_t *b) {
while (b->readpos == b->writepos); // nothing to consume. wait
int next = (b->readpos+1) % BUF_SIZE;
void * res = b->buffer[b->readpos]; b->readpos = next;
return res;
}
buf_t *alloc () {
buf_t *b = (buf_t *)malloc(sizeof(buf_t));
b->writepos = 0; b->readpos = 0; return b;
}
Однако эта реализация еще недостаточно быстра и нуждается в дальнейшей оптимизации. Я пробовал с разными значениями BUF_SIZE
и получил некоторое ускорение. Кроме того, я переместил writepos
перед buffer
и readpos
после buffer
, чтобы убедиться, что обе переменные находятся в разных строках кэша, что также привело к некоторой скорости.
Мне нужно ускорение около 400%. У вас есть идеи, как я могу добиться этого, используя такие вещи, как отступы и т. Д.?