我有一个数据流,它将物理上的64位值输出到缓冲区。当缓冲区达到某个水平时,需要将其重新格式化为连续的16位值。真实的值永远不会超过数据流产生的每个值的64位中的24位,因此这相当于将24b值截断为16b并重新排列缓冲区,因此这些值现在是连续的。我相信我已经找到了最快的方法来做到这一点,但我不确定是否有优化,我可能会错过或更快的方法提供的C++标准实用程序。下面是一个MRE,显示了我的重新格式化功能,以及一个测试工具,用于生成像我遇到的数据和重新格式化的时间。
#include <iostream>
#include <chrono>
#include <unistd.h>
int num_samples = 160000;
void fill_buffer(uint8_t** buffer){
*buffer = (uint8_t*)malloc(num_samples * sizeof(uint64_t));
for (int i = 0; i < num_samples; i += 8){
(*buffer)[i] = rand() % 0xFF;
(*buffer)[i + 1] = rand() % 0xFF;
(*buffer)[i + 2] = rand() % 0xFF;
}
}
void reformat_1(uint8_t* buf){
uint64_t* p_8byte = (uint64_t*)buf;
uint16_t* p_2byte = (uint16_t*)buf;
for (int i = 0; i < num_samples; i++){
p_2byte[i] = p_8byte[i] >> 8;
}
}
int main(int argc, char const* argv[]){
uint8_t* buffer = NULL;
fill_buffer(&buffer);
auto start = std::chrono::high_resolution_clock::now();
reformat_1(buffer);
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
std::cout << "Time taken by function one: " << duration.count() << " microseconds" << std::endl;
return 0;
}
我也很乐意听到关于我的基准测试设置的反馈,我发现有趣的是,使用-O3
,我从文件中读取的实际样本数据大约为130uS,而使用随机生成的数据,我看到的数据更接近1800uS,所以这显然不是一个完美的代表性示例。
另一件事,我会注意到,我会认为将工作对我的实际时间(与合成),但显然不是:虽然num_samples
在这里是一个幻数,但在实践中,它是计算出来的,通常是常数(并不总是),但编译器不会用常数来替换展开循环等(我认为)。
1条答案
按热度按时间b1zrtrql1#
这一微小改进将性能提高了约10%:
为了查看更清晰的数字,我将缓冲区大小增加了100倍,达到16M条目。