我正在读取(以二进制格式)无符号8位整数的文件,然后我需要将其转换为浮点数组。通常我会做以下的事情:
uint8_t *s1_tmp = (uint8_t *)malloc(sizeof(uint8_t)*num_elements);
float *s1 = (float *)malloc(sizeof(float)*num_elements);
fread(s1_tmp, sizeof(uint8_t), num_elements, file_id);
for(int i = 0; i < num_elements; i++){
s1[i] = s1_tmp[i];
}
free(s1_tmp)
缺乏灵感,但它确实有效。但是,目前num_elements
约为270万,因此这个过程非常缓慢且IMO浪费。
有没有更好的方法将8位整数读入浮点数或将uint8_t
数组转换为浮点数组?
答案 0 :(得分:5)
首先,这将是读取数据的I / O限制。其次,它将受内存限制。如果将转换与读数交错,您将获得更好的缓存性能。
选择一些合理的缓冲区大小,这个大小足以获得良好的I / O性能,但又小到足以容纳缓存,可能是8-32 KB左右。读入那么多数据,转换和重复。
例如:
#define BUFSIZE 16384
uint8_t *buffer = malloc(BUFSIZE);
float *s1 = malloc(num_elements * sizeof(float));
int total_read = 0;
int n;
while(total_read < num_elements && (n = fread(buffer, 1, BUFSIZE, file_id)) > 0)
{
n = min(n, num_elements - total_read);
for(int i = 0; i < n; i++)
s1[total_read + i] = (float)buffer[i];
total_read += n;
}
free(buffer);
通过使用SIMD操作一次转换多个项目,您可能还会看到性能提升。但是,整体性能仍会受到来自fread的I / O的瓶颈,因此您可能会从SIMD中看到多少改进将是值得怀疑的。
由于您要转换大量uint8_t
值,因此可以通过使用查找表而不是执行整数到浮点转换来获得一些改进的性能。您只需要一个256浮点值(1 KB)的查找表,它很容易适合缓存。我不知道这是否会更快,所以你肯定应该编写代码来找出最佳选择。