我正在读取(二进制格式)无符号 8 位整数文件,然后我需要将其转换为 float 数组。通常我会做类似下面的事情:
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 位整数作为 float 读取或将 uint8_t
数组转换为 float 数组?
最佳答案
首先,这将是 I/O 绑定(bind)的,因为读入数据。其次,它将是内存绑定(bind)的。如果将转换与读取交错进行,您将获得更好的缓存性能。
选择一些合理的缓冲区大小,它足够大以实现良好的 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
值,因此您完全有可能通过使用查找表而不是进行整数到 float 的转换来提高性能。您只需要一个包含 256 个浮点值 (1 KB) 的查找表,它很容易放入缓存中。我不知道那样会不会更快,所以您绝对应该分析代码以确定最佳选择。
关于c - 如何将大量 uint_8 转换为 C 中的 float 组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12605169/