C++ 用查找表替换math.h exp调用

C++ 用查找表替换math.h exp调用,c++,math.h,C++,Math.h,我想知道修改代码以使用math.hexp的查找表是否有意义,或者当给定-O3标志时,它是否由clang++自动完成 如果不是,是否有一个#pragma可以这样做 澄清 我说的是函数调用的记忆。也就是说,如果函数被传递相同的精确参数(是的,浮点数实际上可以是相同的,如果它们是从常量和整数派生的) 示例 假设我要运行exp(-a*x),其中a不是编译时常量,但一旦设置一次,它就不会被修改。类似地,x可以是10个可能值中的一个,所有这些值都设置一次,不再修改 我对叮当声的细节不太了解,所以我无法详细说

我想知道修改代码以使用
math.h
exp
的查找表是否有意义,或者当给定
-O3
标志时,它是否由
clang++
自动完成

如果不是,是否有一个
#pragma
可以这样做

澄清

我说的是函数调用的记忆。也就是说,如果函数被传递相同的精确参数(是的,浮点数实际上可以是相同的,如果它们是从常量和整数派生的)

示例


假设我要运行
exp(-a*x)
,其中
a
不是编译时常量,但一旦设置一次,它就不会被修改。类似地,
x
可以是10个可能值中的一个,所有这些值都设置一次,不再修改

我对叮当声的细节不太了解,所以我无法详细说明它的作用。但我可以推理它可能会做什么

如果参数是编译时常量,那么优化器可能能够在编译/链接时进行预计算。但这并不是必须的,我也不希望所有的编译器都这么做

如果参数不是编译时常量,并且同一函数中的多个调用使用同一个参数(并且不涉及易失性对象),那么如果优化器知道函数没有副作用,它可能会重新使用结果。我建议您手动执行此优化,只是因为最好不要重复

如果参数不是编译时常量,则可以将结果存储在某个表中以供以后使用,但加载值的内存访问可能比计算本身慢得多,因此这可能会导致悲观的结果


显然,进行这些优化是否有意义将取决于许多方面,如CPU体系结构、缓存等,最重要的是,首先取决于操作是否对性能有任何显著影响。

我不太了解clang的具体情况,因此,我无法详细说明它的作用。但我可以推理它可能会做什么

如果参数是编译时常量,那么优化器可能能够在编译/链接时进行预计算。但这并不是必须的,我也不希望所有的编译器都这么做

如果参数不是编译时常量,并且同一函数中的多个调用使用同一个参数(并且不涉及易失性对象),那么如果优化器知道函数没有副作用,它可能会重新使用结果。我建议您手动执行此优化,只是因为最好不要重复

如果参数不是编译时常量,则可以将结果存储在某个表中以供以后使用,但加载值的内存访问可能比计算本身慢得多,因此这可能会导致悲观的结果


显然,进行这些优化是否有意义将取决于许多方面,如CPU架构、缓存等,最重要的是操作是否对性能有任何显著影响。

浮点参数查找表?对于此类问题,请顺便提一下,这是一个很棒的工具:它不太可能存在,因为分辨率和范围都取决于应用程序。查找边界值之间的浮动可能没有那么快。您手头有具体的问题吗?对于整数,可能值得考虑一个表,甚至对于浮点数,如果您有一些可预测的调用模式(例如
exp(i*x)
,其中
i
是整数,
x
是常量浮点数)。在目前的形式下,这个问题对于浮点参数来说太广泛了。顺便说一句,对于这样的问题,这是一个很棒的工具:它不太可能存在,因为分辨率和范围都取决于应用程序。查找边界值之间的浮动可能没有那么快。您手头有具体的问题吗?对于整数,可能值得考虑一个表,甚至对于浮点数,如果您有一些可预测的调用模式(例如
exp(i*x)
,其中
i
是整数,
x
是常量浮点数)。在当前的形式中,问题太广泛了,imhoSo我如何指定对象是非易失性的?@AlexPetrosyan避免使用
volatile
。我做了一些测试,实现了一个查找表。。。当使用
-O3
编译时,它会自动“缓存”昂贵的操作。我在记忆方面的尝试无疑使代码速度变慢了。@AlexPetrosyan:您可能发现了一种称为公共子表达式消除(CSE)的优化。如果编译器发现对一个已知纯函数的两个参数完全相同的调用,它通常会去掉第二个调用。(纯函数没有副作用。显然,你不能取消对
std::printf
)的两个调用,那么我如何指定对象是非易失性的呢?@AlexPetrosyan避免使用
volatile
。我做了一些测试,实现了一个查找表。。。当使用
-O3
编译时,它会自动“缓存”昂贵的操作。我在记忆方面的尝试无疑使代码速度变慢了。@AlexPetrosyan:您可能发现了一种称为公共子表达式消除(CSE)的优化。如果编译器发现对一个已知纯函数的两个参数完全相同的调用,它通常会去掉第二个调用。(纯函数没有副作用。显然,您不能取消对
std::printf
的两个调用)