c++ - 为什么使用指针会降低性能

标签 c++ performance inheritance allocation

<分区>

假设我有一个类 Manager 做一些工作,然后我有一个 DistributedManager,它继承自 Manager 但重新实现了一些使用多线程的方法。

使用它们的代码是

 Manager<T,W,P> manager(initargs);
 manager.compute(runargs);

 DistributedManager<T,W,P> manager(initargs, 4); // 4 is number of thread to use
 manager.compute(runargs);

然后在某些时候,我希望可以通过类似命令修改我使用的线程数。所以我制作了一个 size_t nbthread = 1 ,它可以通过一个选项进行修改,我将我的代码修改为以下内容:

Manager<T,W,P>* manager;
switch(nbthread)
{
    case 0:
    case 1:
        manager = new Manager<T,W,P>(initargs);
        break;
    default:
        manager = new DistributedManager<T,W,P>(initargs, nbthread);
        break;
}
manager->compute(runargs);

它可以编译并工作...但是我的表现很糟糕!

使用第一种方法和 DistributedManager 和 4 个线程我可以在 500 毫秒内运行,使用第二种方法相同的计算运行时间超过 2000 毫秒。

分配部分不应该那么长:

sizeof(Manager<T,W,P>) : 104
sizeof(DistributedManager<T,W,P>) : 128

出了什么问题?

编辑

基准测试使用

std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
densityfieldptr->compute(particles, massfield, massthreshold, densityfunctor);
std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
printf("computation time: %ld ms\n", std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count());

编辑2:我很蠢

时间增加了大约 4 倍……因为调用的是非多线程版本。使用指向基类的指针在使用这些方法的地方!

virtual 关键字不能用来解决这个问题,因为方法是模板化的

我不得不重新考虑我的模板模式,一切都按预期工作

最佳答案

我同意评论说没有足够的信息来明确说明正在发生的事情,但我有一个理论 ( false sharing ) 对于评论来说太长了,所以这是一个暂定的答案。

两者的主要区别在于存储分配

  • DistributedManager 管理器(initargs, 4);//自动存储分配
  • manager = new DistributedManager(initargs, nbthread);//动态存储分配

自动存储在栈上实现,动态存储在堆上。你说那又怎么样? 那么"new"的实现并不能保证在高速缓存行边界和多个高速缓存行的分配。我之前遇到过性能问题,其中堆上的一个对象与另一个线程访问的另一个对象共享,并且至少其中一个被修改(由线程写入) - 错误共享。这会导致缓存行在运行线程的内核之间来回“乒乓”。这不是逻辑错误,而是性能错误。编译器可能以防止错误共享的方式在堆栈上进行分配,或者它可能恰好在那里不是问题,但可能无法保证,改变一些东西在您的程序中,您可能还会看到自动存储的问题。解决这个问题的唯一方法是使用自定义分配器。

关于c++ - 为什么使用指针会降低性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27277159/

相关文章:

c++ - 使用 Qt/C++ 等到所有线程在主线程中完成

c++ - 为 Qt 项目创建 .deb 包

c++ - Eclipse C++ 未定义引用

javascript - 通过 ajax 响应获取变量或使用 .load() 加载 php 页面是否更快

Java:当对象被声明为基类时访问派生类的成员

c# - 如果调用继承的重载,会调用什么方法?

c++ - 什么是智能指针管理的资源,而它们的内存不是new分配的?

c - 内存性能/缓存难题

java - 从大文件(超过 700MB)中提取模式的更有效方法是什么

html - 为什么 text-decoration 会停止基于子元素定位的继承?