我正在寻求有关解决以下问题的建议。我有一个恒定的数据输入,需要将其添加到缓冲区中,并且在每次迭代时,我都需要将缓冲的数据传递给通过指针接受C样式数组的函数。
我担心效率,因此我考虑了如何在某种循环缓冲区中存储和管理数据,但又将其作为顺序的原始数据来传递给上述功能。
我的当前方法可以总结为以下示例:
#include <iostream>
#include <array>
#include <algorithm>
void foo(double* arr, int size)
{
for (uint k = 0; k < size; k++)
std::cout << arr[k] << ", ";
std::cout << std::endl;
}
int main()
{
const int size = 20;
std::array<double, size> buffer{};
for (double data = 0.0; data < 50.0; data += 1.0)
{
std::move(std::next(std::begin(buffer)), std::end(buffer), std::begin(buffer));
buffer.back() = data;
foo(buffer.data(), size);
}
}
在实际用例中,还需要在开始时将缓冲区填充为数据的“const”大小(我在这里使用引号,因为在编译时可能知道或可能不知道大小,但是一旦知道,它就会永远不会改变)。我将数据存储在
std::array
中(如果在编译时未知大小,则存储在std::vector
中),因为数据在内存中是顺序的。当我需要插入新数据时,我使用正向std::move
移动所有内容,然后手动替换最后一个项目。最后,我只是将std::array::data()
及其大小传递给该函数。乍一看这应该有效,但原因告诉我,由于数据是按顺序存储的,因此整个缓冲区仍将使用
std::move
复制,并且每个插入均为O(n)实际的缓冲区大小可能只有几百个,并且数据将以最大100Hz的频率到达,但是问题是我需要尽快获得被调用函数的结果,所以我不想浪费时间进行缓冲区管理(即使我们说话很少,甚至少于毫秒)。我对此有很多疑问,但他们的候选名单如下:
最佳答案
感谢您的回答沃纳。当我在Repl.it上运行此解决方案时,我得到:
it took an average of 21us and a max of 57382us
为了进行比较,我最初的想法是使用相同的缓冲区大小,结果如下:it took an average of 19us and a max of 54129us
这意味着我最初的方法确实很幼稚:)同时,在等待答案的同时,我提出了以下解决方案:
#include <iostream>
#include <array>
#include <algorithm>
#include <chrono>
void foo(double* arr, int size)
{
for (uint k = 0; k < size; k++)
std::cout << arr[k] << ", ";
std::cout << std::endl;
}
int main()
{
const int buffer_size = 20;
std::array<double, buffer_size*2> buffer{};
int buffer_idx = buffer_size;
for (double data = 0.0; data < 100.0; data += 1.0)
{
buffer.at(buffer_idx - buffer_size) = data;
buffer.at(buffer_idx++) = data;
foo(buffer.data() + buffer_idx - buffer_size, buffer_size);
buffer_idx -= buffer_size * (buffer_idx == buffer_size * 2);
}
}
由于缓冲区的大小不是问题,因此我分配了两倍的内存,并在两个位置插入了数据,但偏移了缓冲区的大小。当我到达终点时,我就像打字机一样回去。我的想法是,我通过再存储一个数据副本来伪造循环缓冲区,这样它就可以读取数据,就像它越过了整个圆圈一样。对于50000的缓冲区大小,这给出了我想要的以下结果:
it took an average of 0us and a max of 23us
关于c++ - C++中的有效循环缓冲区,将传递给C样式数组函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62892744/