【发布时间】:2010-02-04 21:10:41
【问题描述】:
我有一个用于 C++ 中背包的动态编程算法。当它被实现为一个函数并访问传递给它的变量时,它需要 22 秒才能在特定实例上运行。当我将它作为我的类 KnapsackInstance 的成员函数并让它使用作为该类的数据成员的变量时,它开始需要 37 秒才能运行。据我所知,只有访问成员函数会通过 vtable,所以我无法解释可能发生的情况。
这是函数的代码
int KnapsackInstance::dpSolve() {
int i; // Current item number
int d; // Current weight
int * tbl; // Array of size weightLeft
int toret;
tbl = new int[weightLeft+1];
if (!tbl) return -1;
memset(tbl, 0, (weightLeft+1)*sizeof(int));
for (i = 1; i <= numItems; ++i) {
for (d = weightLeft; d >= 0; --d) {
if (profitsWeights.at(i-1).second <= d) {
/* Either add this item or don't */
int v1 = profitsWeights.at(i-1).first + tbl[d-profitsWeights.at(i-1).second];
int v2 = tbl[d];
tbl[d] = (v1 < v2 ? v2 : v1);
}
}
}
toret = tbl[weightLeft];
delete[] tbl;
return toret;
}
tbl 是 DP 表的一列。我们从第一列开始,一直到最后一列。 ProfitWeights 变量是成对的向量,其中第一个元素是利润,第二个元素是权重。 toret 是要返回的值。
这里是原函数的代码:-
int dpSolve(vector<pair<int, int> > profitsWeights, int weightLeft, int numItems) {
int i; // Current item number
int d; // Current weight
int * tbl; // Array of size weightLeft
int toret;
tbl = new int[weightLeft+1];
if (!tbl) return -1;
memset(tbl, 0, (weightLeft+1)*sizeof(int));
for (i = 1; i <= numItems; ++i) {
for (d = weightLeft; d >= 0; --d) {
if (profitsWeights.at(i-1).second <= d) {
/* Either add this item or don't */
int v1 = profitsWeights.at(i-1).first + tbl[d-profitsWeights.at(i-1).second];
int v2 = tbl[d];
tbl[d] = (v1 < v2 ? v2 : v1);
}
}
}
toret = tbl[weightLeft];
delete[] tbl;
return toret;
}
这是在 Debian Lenny 上运行的,打开了 g++-4.3.2 和 -O3 -DNDEBUG
谢谢
【问题讨论】:
-
我们还需要查看非类函数才能做出明智的评论。
-
我想我们需要一种比较方法……而且,你有潜在的内存泄漏;如果抛出异常,
delete[] tbl将不会被调用。 -
除了类成员函数与非成员函数的问题外,它可能有助于将profitWeight.at(i-1) 提升出for(d =...) 循环并将其分配给如果您的编译器尚未为您执行本地(寄存器)变量。
标签: c++ performance dynamic-programming compiler-optimization