如何将一个巨大的头部分配数组设置为特定的浮点数 C++

Posted

技术标签:

【中文标题】如何将一个巨大的头部分配数组设置为特定的浮点数 C++【英文标题】:How to set a huge head allocate array as specific float number C++ 【发布时间】:2020-06-10 13:39:43 【问题描述】:

首先,我使用英特尔数学内核库 API 分配了一个巨大的块内存。之后,我想将此数组设置为特定值,例如 1234.5678。我打算用void* memset( void* dest, int ch, std::size_t count );函数,但是这个函数好像只能设置int值。我可以使用简单的 for 循环来解决这个问题。但是,我认为使用for loop 为这么大的块设置初始值并不是很有效。所以我的问题是

    我还有其他方法可以在不使用for loop 的情况下初始化如此巨大的块内存吗?

【问题讨论】:

为了确保我理解,您想将 每个数组元素 的值设置为 1234.5678 吗?如果是这样,您可能需要使用 std::fillstd::fill_n 为什么你认为 for 循环会低效。您是否尝试过并发现它太慢了?编译器非常擅长优化您编写的代码。基本上首选应该是写最直接的代码,让编译器为你做优化。 @john 如果要将值设置为某个整数,可以比较 memset 和 for 循环之间的性能。你会发现位操作要快得多。更重要的是,如果你使用for循环,你必须支付检查终止条件的成本。所以我只是想看看是否有其他方法可以做到这一点。 @CoryKramer 我认为这两个函数只适用于定义迭代器的包含。 @Sean 好吧,你说它是一个数组。语言指定了数组的迭代器。它是一个指针。 【参考方案1】:

您可以使用std::fill_n 为数组的每个值分配一个值

#include <algorithm>

std::fill_n(data, count, 1234.5678);

请注意,即使您使用原始 for 循环,许多编译器也会生成相同的代码

for (std::size_t i = 0; i < count; ++i)

    data[i] = 1234.5678;

参见这个Compiler Explorer 示例,以上两种情况都会生成相同的汇编代码

void fill_a(double *,unsigned __int64) PROC                         ; fill_a
$LN14:
        sub     rsp, 8
        test    rdx, rdx
        je      SHORT $LN6@fill_a
        mov     QWORD PTR [rsp], rdi
        mov     rax, 4653144502051863213      ; 40934a456d5cfaadH
        mov     rdi, rcx
        mov     rcx, rdx
        rep stosq
        mov     rdi, QWORD PTR [rsp]
$LN6@fill_a:
        add     rsp, 8
        ret     0

【讨论】:

我使用mkl分配内存,我认为不应该有迭代器。 @Sean 只要你有(或可以转换为)double*一个迭代器【参考方案2】:

我打算使用 void* memset( void* dest, int ch, std::size_t count );函数,不过好像这个函数只能设置int值。

您实际上可以使用 memset 来设置 floats1 的值,或者实际上是任何可简单复制的类型。 int ch 只是将被复制到数据上的字节的值。

但这确实意味着您不能使用 memset 为多字节类型设置任意值,因为所有字节都会重复。例如,您可以将整数设置为 0,即四个 0 字节,或者将一个四字节整数设置为 4369,即四个 1 字节。

如果是符合 32 位 IEEE 754 的浮点数,您可以将 memset 设置为值 785.066650391F,例如,这样做:std::memset(ptr, count * sizeof(float), 0x44)。这是因为该特定数字由四个重复的 0x44 字节组成。

具体值,例如 1234.5678

这个特定的值不包含重复的字节,所以不能用memset创建。

我可以使用简单的for循环来解决这个问题

正确。

但是,我认为使用for循环为这么大的块设置初始值并不是很有效

您可能会惊讶地发现编译器在优化循环方面有多出色。有时他们用调用 memset 替换循环(当它有相同的结果时);其他时候,它们会产生比调用 memset 更快的代码(好吧,至少在理论上。编译器也知道 memset 的作用,并且还可以用从循环中生成的内联代码替换对它的调用,如果它认为它可能会更快)。

但是,您不需要自己编写循环。正如Cory Kramer 所示,标准库对此有一个算法。


1 需要注意的是语言标准没有指定浮点类型的位表示,因此结果值在技术上可能是无意义的,甚至是陷阱表示。另一方面,IEEE 754 相当普遍,您可以根据用例依赖它。

【讨论】:

以上是关于如何将一个巨大的头部分配数组设置为特定的浮点数 C++的主要内容,如果未能解决你的问题,请参考以下文章

c语言中如何将10进制的浮点数转化为16进制数

如何将小数字转换为python中的浮点数? [复制]

如何将浮点值附加为字典中的浮点数?

将字符串中的数字转换为 c 中的浮点数:atof()、strtof() 不起作用

如何从 C 中的浮点数中提取有偏指数?

如何将“20,54”解析为 js 中的浮点数? [复制]