- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我测试了memcpy()
的速度注意到速度在 i*4KB 处急剧下降。结果如下:Y轴是速度(MB/秒),X轴是memcpy()
的缓冲区大小。 ,从 1KB 增加到 2MB。子图 2 和子图 3 详细说明了 1KB-150KB 和 1KB-32KB 的部分。
环境:
CPU : Intel(R) Xeon(R) CPU E5620 @ 2.40GHz
操作系统:2.6.35-22-generic#33-Ubuntu
GCC 编译器标志:-O3 -msse4 -DINTEL_SSE4 -Wall -std=c99
我想它一定与缓存有关,但我无法从以下缓存不友好的情况中找到原因:
void memcpy_speed(unsigned long buf_size, unsigned long iters){
struct timeval start, end;
unsigned char * pbuff_1;
unsigned char * pbuff_2;
pbuff_1 = malloc(buf_size);
pbuff_2 = malloc(buf_size);
gettimeofday(&start, NULL);
for(int i = 0; i < iters; ++i){
memcpy(pbuff_2, pbuff_1, buf_size);
}
gettimeofday(&end, NULL);
printf("%5.3f\n", ((buf_size*iters)/(1.024*1.024))/((end.tv_sec - \
start.tv_sec)*1000*1000+(end.tv_usec - start.tv_usec)));
free(pbuff_1);
free(pbuff_2);
}
pbuff_1
之间添加了一个 2KB 的虚拟缓冲区。和
pbuff_2
.它有效,但我不确定 Leeor 的解释。
最佳答案
内存通常以 4k 页组织(尽管也支持更大的尺寸)。您的程序看到的虚拟地址空间可能是连续的,但在物理内存中不一定如此。维护虚拟地址到物理地址的映射(在页面映射中)的操作系统通常也会尝试将物理页面保持在一起,但这并不总是可能的,并且它们可能会断裂(特别是在长时间使用时它们可能会偶尔交换) )。
当您的内存流跨越 4k 页面边界时,CPU 需要停止并获取新的翻译——如果它已经看到该页面,它可能会缓存在 TLB 中,并且访问被优化为最快,但如果这是第一次访问(或者如果您有太多页面供 TLB 保留),CPU 将不得不停止内存访问并开始对页面映射条目进行页面遍历 - 这相对较长,因为实际上每个级别自己读取的内存(在虚拟机上它甚至更长,因为每个级别可能需要在主机上进行完整的页面遍历)。
您的 memcpy 函数可能有另一个问题——当第一次分配内存时,操作系统只会将页面构建到页面映射中,但由于内部优化,将它们标记为未访问和未修改。第一次访问可能不仅会调用页面遍历,还可能会通知操作系统该页面将被使用(并存储到目标缓冲区页面中),这将需要向某些操作系统处理程序进行昂贵的转换。
为了消除这种噪音,分配缓冲区一次,执行多次复制,并计算分摊时间。另一方面,这会给你“温暖”的性能(即在缓存预热之后),所以你会看到缓存大小反射(reflect)在你的图表上。如果您想在不遭受分页延迟的情况下获得“冷”效果,您可能需要在迭代之间刷新缓存(只要确保您没有时间)
编辑
重读这个问题,你似乎在做一个正确的测量。我的解释的问题是它应该在4k*i
之后显示逐渐增加。 ,因为在每次这样的下降时,您都会再次支付罚款,但随后应该享受免费乘车,直到下一个 4k。它没有解释为什么会有这样的“尖峰”,在它们之后速度恢复正常。
我认为您面临与问题中链接的关键步幅问题类似的问题 - 当您的缓冲区大小为 4k 时,两个缓冲区将与缓存中的相同集合对齐并相互碰撞。你的 L1 是 32k,所以一开始看起来不是问题,但假设数据 L1 有 8 种方式,它实际上是对相同集合的 4k 环绕,并且你有 2*4k 块具有完全相同的对齐方式(假设分配是连续完成的)所以它们在相同的集合上重叠。 LRU 不能完全按照您的预期工作就足够了,并且您将继续遇到冲突。
为了检查这一点,我会尝试在 pbuff_1 和 pbuff_2 之间分配一个虚拟缓冲区,使其大小为 2k 并希望它打破对齐。
编辑2:
好的,既然这有效,是时候详细说明了。假设您在 0x1000-0x1fff
范围内分配了两个 4k 数组和 0x2000-0x2fff
. L1 中的 set 0 将包含 0x1000 和 0x2000 处的行,set 1 将包含 0x1040 和 0x2040,依此类推。在这些大小下,您还没有遇到任何抖动问题,它们都可以共存而不会溢出缓存的关联性。但是,每次执行迭代时,您都会有一个负载和一个访问同一个集合的存储 - 我猜这可能会导致硬件冲突。更糟糕的是 - 你需要多次迭代来复制一行,这意味着你有 8 个加载 + 8 个存储的拥塞(如果你向量化,则更少,但仍然很多),所有这些都针对同一个糟糕的集合,我很漂亮肯定有一堆碰撞隐藏在那里。
我也看到 Intel optimization guide对此有话要说(见 3.6.8.2):
4-KByte memory aliasing occurs when the code accesses two different memory locations with a 4-KByte offset between them. The 4-KByte aliasing situation can manifest in a memory copy routine where the addresses of the source buffer and destination buffer maintain a constant offset and the constant offset happens to be a multiple of the byte increment from one iteration to the next.
...
loads have to wait until stores have been retired before they can continue. For example at offset 16, the load of the next iteration is 4-KByte aliased current iteration store, therefore the loop must wait until the store operation completes, making the entire loop serialized. The amount of time needed to wait decreases with larger offset until offset of 96 resolves the issue (as there is no pending stores by the time of the load with same address).
关于performance - 为什么 memcpy() 的速度每 4KB 就会急剧下降?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21038965/
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 8年前关闭。 Improve t
暂时忘记能力的定义,只关注能力的“检查”(使用“授权!”),我看到 CanCan 添加了大约 400 毫秒,用于简单地检查用户是否具有特定的能力主题/模型。 这是预期的吗(我假设不是)?或者,有没有可
我正在阅读有关 Swift 的教程 ( http://www.raywenderlich.com/74438/swift-tutorial-a-quick-start ),它预定义为不显式设置类型,因
这主要是由于对 SQL 问题的回答。由于性能原因,有意省略了 UDF 和子查询。我没有包括可靠性并不是说它应该被视为理所当然,但代码必须工作。 性能永远是第一位的吗?提供了许多以性能为主要优先事项的答
我已经编写了一个简单的测试平台来测量三种阶乘实现的性能:基于循环的,非尾递归的和尾递归的。 Surprisingly to me the worst performant was the loop o
我已将 ui-performance 插件应用到我的应用程序中。不幸的是,在开发模式下运行应用程序时它似乎不起作用。例如,我的 javascript 导入是用“vnull”版本呈现的。 例如 不会
我有一个我操作的 F# 引用(我在各处添加对象池以回收经常创建和删除的短期对象)。我想运行结果报价;现在我使用了 F# PowerPack,它提供了将引用转换为表达式树和委托(delegate)的方法
我正在尝试在 Spark 服务器上运行 SparklyR 库中的机器学习算法。 1 个簇 8 核 24G内存 Ubuntu 16.04 星火2.2 独立配置 1名师傅/2名 worker 每个执行器的
我有一个数据库(准确地说是在 postgres 上运行),具有以下结构: user1 (schema) | - cars (table) - airplanes (table, again) .
我的应用程序在我的 iPad 上运行。但它的表现非常糟糕——我的速度低于 15fps。谁能帮我优化一下? 它基本上是一个轮子(派生自 UIView),包含 12 个按钮(派生自 UIControl)。
在完成“Scala 中的函数式编程原则”@coursera 类(class)第 3 周的作业时,我发现当我实现视频类(class)中所示的函数联合时: override def union(tha
我正在重构我的一个 Controller 以使其成为一项服务,我想知道不将整个服务容器注入(inject)我的 Controller 是否会对性能产生影响。 这样效率更高吗: innova.path.
我有一个要显示的内容很大的文件。例如在显示用户配置文件时, 中的每个 EL 表达式需要一个 userId 作为 bean 的参数,该参数取自 session 上下文。我在 xhtml 文件中将这个 u
我非常了解 mipmapping。我不明白(在硬件/驱动程序级别)是 mipmapping 如何提高应用程序的性能(至少这是经常声称的)。在执行片段着色器之前,驱动程序不知道要访问哪个 mipmap
这个问题在这里已经有了答案: 10年前关闭。 Possible Duplicate: What's the (hidden) cost of lazy val? (Scala) Scala 允许定义惰
一些文章建议现在 build() 包含在 perform() 本身中,而其他人则建议当要链接多个操作时使用 build().perform()一起。 最佳答案 build() 包含在 perform(
Postgres docs说 For best optimization results, you should label your functions with the strictest vol
阅读Zero-cost abstractions看着 Introduction to rust: a low-level language with high-level abstractions我尝
我想在 MQ 服务器上部署 SSL,但我想知道我当前的 CPU 容量是否支持 SSL。 (我没有预算增加 CPU 内核和 MQ PVU 的数量) 我的规范: Windows 2003 服务器 SP2,
因此,我在 Chrome 开发者工具 的性能 选项卡内的时间 部分成功地监控了我的 React Native 应用程序的性能。 突然在应用程序的特定重新加载时,Timings 标签丢失。 我已尝试重置
我是一名优秀的程序员,十分优秀!