提高C循环缓冲效率

Gur*_*rba 10 c embedded circular-buffer

我想帮助提高循环缓冲区代码的效率.

我看了一下stackoverflow,发现(几乎)循环缓冲区的所有主题都是关于这种缓冲区的使用或循环缓冲区的基本实现.我真的需要有关如何使其超级高效的信息.

计划是将此缓冲器与STM32F4微控制器一起使用,该微控制器具有单个精确FPU.我计划大量使用write()和readn()函数.我们实际上只是在这里谈了几百万个电话,所以在这里刮几个时钟周期,确实会有所作为.

我将把最重要的代码放在这里,完整的缓冲区代码可以通过http://dl.dropbox.com/u/39710897/circular%20buffer.rar获得.

任何人都可以向我提供一些关于如何提高此缓冲区效率的指示吗?

#define BUFF_SIZE 3             // buffer size set at compile time

typedef struct buffer{
    float buff[BUFF_SIZE];
    int readIndex;
    int writeIndex;
}buffer;

/********************************\
* void write(buffer* buffer, float value)
* writes value into the buffer
* @param buffer* buffer
*   pointer to buffer to be used
* @param float value
*   valueto be written in buffer
\********************************/
void write(buffer* buffer,float value){
    buffer->buff[buffer->writeIndex]=value;
    buffer->writeIndex++;
    if(buffer->writeIndex==BUFF_SIZE)
        buffer->writeIndex=0;
}

/********************************\
* float readn(buffer* buffer, int Xn)
* reads specified value from buffer
* @param buffer* buffer
*   pointer to buffer to be read from
* @param int Xn
*   specifies the value to be read from buffer counting backwards from the most recently written value
*   i.e. the most recently writen value can be read with readn(buffer, 0), the value written before that with readn(buffer, 1)
\********************************/
float readn(buffer* buffer, int Xn){
    int tempIndex;

    tempIndex=buffer->writeIndex-(Xn+1);
    while(tempIndex<0){
        tempIndex+=BUFF_SIZE;
    }

    return buffer->buff[tempIndex];
}
Run Code Online (Sandbox Code Playgroud)

val*_*ldo 13

正如"Oli Charlesworth"建议的那样 - 如果你的缓冲区大小是2的幂,你就能够简化一些事情.我想编写读/写函数体,这样意图就更清晰了.

#define BUFF_SIZE (4U)
#define BUFF_SIZE_MASK (BUFF_SIZE-1U)

struct buffer {
    float buff[BUFF_SIZE];
    unsigned writeIndex;
};

void write(struct buffer *buffer, float value) {
    buffer->buff[(++buffer->writeIndex) & BUFF_SIZE_MASK] = value;
}

float readn(struct buffer *buffer, unsigned Xn){
    return buffer->buff[(buffer->writeIndex - Xn) & BUFF_SIZE_MASK];
}
Run Code Online (Sandbox Code Playgroud)

一些解释.请注意,根本没有分支(if).我们不会将数组索引限制为数组边界,而是将其与掩码进行AND运算.

if不是将访问索引计算为

if

我们正在使用:

if

这可以假设2补充算术.也就是说,为了使整数为负,我们对它的所有位都不做,然后加1.但是因为你想从数字中减去1 - 只做NOT就是所需要的.

  • 只要使用位掩码,就应该切换到`unsigned`索引类型.那么你不必争论2补充或类似的东西. (3认同)
  • 非常感谢您,这使我的代码速度提高了大约 6.5 倍!我认为这是一个相当显着的进步 (2认同)
  • @valdo writeIndex最终将溢出 (2认同)

Oli*_*rth 11

如果您可以使缓冲区大小为2的幂,则可以使用无条件位掩码替换零检查.在大多数处理器上,这应该更快.