我想提高动态链接库(DLL)的性能。
为此,我想使用 cos()和 sin()的查找表,因为我使用了很多。
由于我想要获得最大性能,我想创建一个从 0到2PI 的表,其中包含生成的cos和sin计算。
为了在精确度方面取得好成绩,我认为每个函数1 mb的表是大小和精度之间的良好交易。
我想知道如何在不使用外部文件的情况下创建和使用这些表(因为它是一个DLL):我想将所有内容保存在一个文件中。
此外,我不想在插件启动时计算sin和cos函数:它们必须计算一次并放入标准向量。
但是我如何在C ++中做到这一点?
EDIT1:来自jons34yp的代码非常适合创建矢量文件。
我做了一个小基准测试,发现如果你需要良好的精度和良好的速度,你可以做一个250000单位矢量和它们之间的线性插值,你将有7.89E-11最大误差(!),它是最快的我试过的所有近似值(它比sin()快12倍(完全快13,296 x)
答案 0 :(得分:3)
最简单的解决方案是编写一个单独的程序,创建一个包含矢量定义的.cc
文件。
例如:
#include <iostream>
#include <cmath>
int main()
{
std::ofstream out("values.cc");
out << "#include \"static_values.h\"\n";
out << "#include <vector>\n";
out << "std::vector<float> pi_values = {\n";
out << std::precision(10);
// We only need to compute the range from 0 to PI/2, and use trigonometric
// transformations for values outside this range.
double range = 3.141529 / 2;
unsigned num_results = 250000;
for (unsigned i = 0; i < num_results; i++) {
double value = (range / num_results) * i;
double res = std::sin(value);
out << " " << res << ",\n";
}
out << "};\n"
out.close();
}
请注意,这不太可能提高性能,因为此大小的表可能不适合您的L2缓存。这意味着大部分三角计算需要访问RAM;每次这样的访问大约需要几百个CPU周期。
顺便问一下,你看过近似的SSE SIMD三角函数库吗?这看起来像是一个很好的用例。
答案 1 :(得分:2)
您可以使用预计算而不是将它们预先存储在可执行文件中:
double precomputed_sin[65536];
struct table_filler {
table_filler() {
for (int i=0; i<65536; i++) {
precomputed_sin[i] = sin(i*2*3.141592654/65536);
}
}
} table_filler_instance;
这样,表在程序启动时只计算一次,它仍然在固定的内存地址。之后tsin
和tcos
可以内联实现
inline double tsin(int x) { return precomputed_sin[x & 65535]; }
inline double tcos(int x) { return precomputed_sin[(x + 16384) & 65535]; }
答案 2 :(得分:0)
这类问题的通常答案是写一个小问题
生成带有值的C ++源文件的程序
一个表,并将其编译到您的DLL中。如果你在想
表有128000个条目(128000双打是1MB),但是,
您可能会遇到编译器中的某些内部限制。
在这种情况下,您可以考虑将值写入
一个文件作为内存转储,并在加载时mmap
此文件
DLL。 (在Windows下,我想你甚至可以把它放在第二位
将文件放入DLL文件的第二个流中,这样就不会有了
分发第二个文件。)