【发布时间】:2015-03-14 22:01:20
【问题描述】:
我正在写一个图形引擎作为大学作业,最近尝试优化我的部分代码,但优化似乎反而减慢了速度。
这个特定的代码部分处理 2D Lindenmayer 系统并将它们转换为“line2D”对象列表,这些对象可以被程序的另一部分处理成图像。
在这样做时,它使用 sin 和 cos 来计算下一个点的坐标,并且因为 sin 和 cos 是浮点运算,我认为这些会很耗时,尤其是在更复杂的 lindenmayer 系统中。所以我创建了一个对象类“cossinlist”,它从 .txt 文件中将 0 到 359 度之间的每个整数角度(转换为 rad)的 cos 和 sin 的值导入到两个名为“coslist”和“sinlist”的地图中作为关键。这样,在处理包含小数部分的角度时,我只需要做实际的翻牌。
然后我决定在一个相对密集的系统上测量优化和不优化的执行时间(通过注释掉它):引擎在 33.4016 秒内生成图像,而没有优化只需要 25.3686 秒。这是一个很大的差异,但不是以预期的方式。我做了更多测试,所有测试都给出了相似比例的差异,所以现在我想知道......是什么导致了这种差异?
功能:
img::EasyImage LSystem2D(const unsigned int size, const ini::DoubleTuple & backgroundcolor, LParser::LSystem2D & System, const ini::DoubleTuple & color)
{
CosSinList cossinlist;
std::string string;
Lines2D Lines;
double origin = 0;
Point2D currentpos(origin, origin);
Point2D newpos(origin, origin);
std::stack<Point2D> savedpositions;
double currentangle = System.get_starting_angle();
std::stack<double> savedangles;
const img::Color linecolor(color.at(0)*255,color.at(1)*255,color.at(2)*255);
const img::Color BGcolor(backgroundcolor.at(0)*255,backgroundcolor.at(1)*255,backgroundcolor.at(2)*255);
string = ReplaceLsystem(System, (System.get_initiator()), (System.get_nr_iterations()));
bool optimizedangle = false;
if(System.get_angle() == rint(System.get_angle()) && (System.get_starting_angle() == rint(System.get_starting_angle()))
{
optimizedangle = true;
}
for(char& c : string)
{
if(currentangle > 359){currentangle -= 360;}
if(currentangle < -359){currentangle += 360;}
if(System.get_alphabet().count(c) != 0)
{
/*if(optimizedangle == true)
{
if(currentangle >= 0)
{
newpos.X = currentpos.X+(cossinlist.coslist[currentangle]);
newpos.Y = currentpos.Y+(cossinlist.sinlist[currentangle]);
}
else
{
newpos.X = currentpos.X+(cossinlist.coslist[360+currentangle]);
newpos.Y = currentpos.Y+(cossinlist.sinlist[360+currentangle]);
}
}
else
{*/
newpos.X = currentpos.X+cos(currentangle*PI/180);
newpos.Y = currentpos.Y+sin(currentangle*PI/180);
//}
if(System.draw(c))
{
Lines.push_back(Line2D(currentpos,newpos,linecolor));
currentpos = newpos;
}
else
{
currentpos = newpos;
}
}
else if(c=='-')
{
currentangle -= System.get_angle();
}
else if(c=='+')
{
currentangle += System.get_angle();
}
else if(c=='[')
{
savedpositions.push(currentpos);
savedangles.push(currentangle);
}
else if(c==']')
{
currentpos = savedpositions.top();
savedpositions.pop();
currentangle = savedangles.top();
savedangles.pop();
}
}
return Drawlines2D(Lines, size, BGcolor);
}
SinCosList 类:
#include <fstream>
#include <iostream>
#include <map>
#include "CosSinList.h"
using namespace std;
CosSinList::CosSinList()
{
string line;
std::fstream cosstream("coslist.txt", std::ios_base::in);
double a;
double i = 0;
while (cosstream >> a)
{
coslist[i] = a;
i += 1;
}
std::fstream sinstream("sinlist.txt", std::ios_base::in);
i = 0;
while (sinstream >> a)
{
sinlist[i] = a;
i += 1;
}
};
CosSinList::~CosSinList(){};
“优化”被注释掉的方式与我在速度测试期间注释掉的方式相同,只有对象的实际使用被注释掉(SinCosList 仍在初始化和检查它是否可以使用的布尔值还在初始化中)
【问题讨论】:
-
你使用了什么编译器,你给了它什么优化设置,你有没有预热你的缓存,你有没有多次运行基准测试?
-
您做出了一个相当幼稚的假设,即浮点运算很慢,并且访问更多内存(对 CPU 缓存施加更大压力)比仅要求 CPU 计算 cos 或 sin 更快.您的代码不是更快,因为它要求 CPU 执行在现代 CPU 上效率较低的事情。
-
我冒昧地猜测现代 CPU 已经针对 cos 和 sin 进行了很好的优化
-
@FelixNeijzen 您的编译器标志不包括任何优化标志,例如
-O3? -
恕我直言,如果在没有优化的情况下编译所有关于优化的问题(即对于 GCC -O2 或类似的),则应立即关闭它们。如果您甚至不启用函数内联,那么谈论 C++ 代码的性能完全是在浪费每个人的时间,您只是在衡量抽象损失。
标签: c++ optimization floating-point