在c++; 我在C++中有一个背包动态规划算法。当它作为一个函数实现并访问传递给它的变量时,在一个特定实例上运行需要22秒。当我让它成为我的类背包实例的成员函数并让它使用作为该类数据成员的变量时,它开始运行37秒。据我所知,只有访问成员函数才能通过vtable,因此我无法解释可能发生的情况
这是函数的代码在c++; 我在C++中有一个背包动态规划算法。当它作为一个函数实现并访问传递给它的变量时,在一个特定实例上运行需要22秒。当我让它成为我的类背包实例的成员函数并让它使用作为该类数据成员的变量时,它开始运行37秒。据我所知,只有访问成员函数才能通过vtable,因此我无法解释可能发生的情况,c++,performance,dynamic-programming,compiler-optimization,C++,Performance,Dynamic Programming,Compiler Optimization,这是函数的代码 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)); f
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;
}
int背包实例::dpSolve(){
int i;//当前项目编号
int d;//当前权重
int*tbl;//大小为left的数组
int托雷特;
tbl=新整数[weightLeft+1];
如果(!tbl)返回-1;
memset(tbl,0,(weightLeft+1)*sizeof(int));
对于(i=1;i=0;--d){
if(profitsWeights.at(i-1).second在典型实现中,成员函数接收指向实例数据的指针作为隐藏参数(this
)。因此,通常通过指针访问成员数据,这可能是您看到的速度减慢的原因
另一方面,只需查看一个版本的代码,就很难做比猜测更多的事情
在查看了这两段代码之后,我想我应该更像这样编写成员函数:
int KnapsackInstance::dpSolve() {
std::vector<int> tbl(weightLeft+1, 0);
std::vector<pair<int, int> > weights(profitWeights);
int v1;
for (int i = 0; i <numItems; ++i)
for (int d = weightLeft; d >= 0; --d)
if ((weights[i+1].second <= d) &&
((v1 = weights[i].first + tbl[d-weights[i-1].second])>tbl[d]))
tbl[d] = v1;
return tbl[weightLeft];
}
int背包实例::dpSolve(){
标准::向量tbl(权重左+1,0);
标准:向量权重(profitWeights);
int v1;
对于(int i=0;i=0;--d)
如果((权重[i+1]。第二个待定[d]))
tbl[d]=v1;
返回tbl[weightLeft];
}
我们也需要查看非类函数,以便进行合理的注释。我认为我们需要一种比较方法……此外,您可能存在内存泄漏;delete[]如果抛出异常,将不会调用tbl
。除了类成员函数与非成员函数的问题外,它可能有助于将profitsWeight.at(i-1)从for(d=…)循环中提升出来,并将其分配给一个局部(register)变量(如果您的编译器尚未为您执行)。尽管您对(这一点)是正确的隐式传递,在循环的第一次传递之后,这应该无关紧要。想想看:一旦它被访问一次,它就应该被缓存。在许多处理器上,取消引用指针可以通过两条指令来完成:一条指令加载指针,一条指令以索引延迟模式加载数据。相比之下,加载变量通常只会导致ne指令。任何开销都不会引起注意,特别是考虑到编译器优化和硬件级指令重新排序的攻击性。@San Jacinto:你可能是对的,但话说回来,也许不是。正如我在文章中暗示的,当时问题中只有一个版本的代码,所以我只能从“一次是成员函数,另一次不是",在这种情况下唯一的区别是通过此
进行访问。不过,我可以看到除指针解引用之外的其他可能会导致瓶颈,例如通过此
进行的所有访问都会阻止一些并行执行。但很难猜测…我为profitsWeights vector创建了一个本地别名,时间过得很快恢复正常,谢谢
int KnapsackInstance::dpSolve() {
std::vector<int> tbl(weightLeft+1, 0);
std::vector<pair<int, int> > weights(profitWeights);
int v1;
for (int i = 0; i <numItems; ++i)
for (int d = weightLeft; d >= 0; --d)
if ((weights[i+1].second <= d) &&
((v1 = weights[i].first + tbl[d-weights[i-1].second])>tbl[d]))
tbl[d] = v1;
return tbl[weightLeft];
}