C 正在寻找线程同步性能问题的解释
当使用内核对象来同步运行在不同CPU上的线程时,使用Windows Server 2008 R2相对于其他操作系统是否会有额外的运行时成本 编辑:从答案中可以看出,这个问题还应该包括“当以较低的CPU利用率水平运行时”这句话。我在自己对这个问题的回答中包含了更多信息 背景 我开发的产品使用共享内存和信号量在进程之间进行通信(当两个进程在同一台机器上运行时)。有关Windows Server 2008 R2性能问题的报告(在此之后我将其缩短为Win2008R2)使我发现,与其他操作系统相比,Win2008R2上两个线程之间共享信号量的速度相对较慢 复制它 我能够通过在两个线程上同时运行以下代码位来复制它:C 正在寻找线程同步性能问题的解释,c,multithreading,performance,synchronization,windows-server-2008,C,Multithreading,Performance,Synchronization,Windows Server 2008,当使用内核对象来同步运行在不同CPU上的线程时,使用Windows Server 2008 R2相对于其他操作系统是否会有额外的运行时成本 编辑:从答案中可以看出,这个问题还应该包括“当以较低的CPU利用率水平运行时”这句话。我在自己对这个问题的回答中包含了更多信息 背景 我开发的产品使用共享内存和信号量在进程之间进行通信(当两个进程在同一台机器上运行时)。有关Windows Server 2008 R2性能问题的报告(在此之后我将其缩短为Win2008R2)使我发现,与其他操作系统相比,Win
for ( i = 0; i < N; i++ )
{
WaitForSingleObject( globalSem, INFINITE );
ReleaseSemaphore( globalSem, 1, NULL );
}
测试中的两个线程都运行了一百万次迭代。这些测试都在相同的机器上运行。Win Server 2008和Server 2003编号来自双引导计算机。Win 7机器具有完全相同的规格,但是不同的物理机器。本例中的机器为联想T420笔记本电脑,核心为i5-2520M 2.5GHz。显然不是服务器类机器,但我在真正的服务器类硬件上得到了类似的结果。括号中的数字是第一列与给定列的比率
有没有解释为什么这一个操作系统似乎会为跨CPU的内核级同步带来额外的费用?或者您是否知道可能会影响这一点的一些配置/调优参数
虽然这会使这篇文章变得非常冗长和冗长,但如果有人想要的话,我可以发布上面这些数字来自的测试代码的增强版本。这将显示循环逻辑的实施和测试的自旋锁版本
扩展背景
试着回答一些不可避免的问题,关于为什么事情是这样做的。我也一样。。。当我读到一篇帖子时,我常常想知道为什么我会问。以下是一些澄清的尝试:
- 什么是应用程序?它是一个数据库服务器。在某些情况下,客户在与服务器相同的机器上运行客户机应用程序。在这种情况下,使用共享内存进行通信(与套接字相比)会更快。这个问题与共享内存通信有关
- 工作负载真的那么依赖于事件吗?好。。。共享内存通信是使用命名信号量实现的。客户机发出信号量,服务器读取数据,服务器在响应就绪时向客户机发出信号量。在其他平台上,它的速度非常快。在Win2008R2上,它不是。它还非常依赖于客户应用程序。如果他们编写时向服务器发出大量的小请求,那么这两个进程之间就会有大量的通信
- 可以使用轻型锁吗?可能地我已经在看了。但它独立于原始问题
- 很可能是操作系统安装配置不同。可能慢系统被配置为不允许多个线程同时调度进程。如果其他一些高优先级进程总是(或大部分)准备好运行,那么唯一的选择就是让线程按顺序运行,而不是并行运行。这不是一个合理的基准测试,您的信号量总是在同一进程中被冻结(因此可能在同一CPU/核心上)。在现实世界中,锁定成本的一个重要部分是当不同的CPU/内核争夺对内存区域的独占访问(在缓存之间来回反弹)时所涉及的内存访问。寻找一些更真实的基准测试(抱歉,不是我的领域),用(人为的,但真实的)测试数据(更好的)度量(应用程序的一些简化版本)
[基准测试的测试数据永远不应该是用于测试或回归测试的数据:后面提到的(可能很少使用)极端情况,你需要“典型”的基准测试运行。]从评论中得出一个答案: 可能服务器未设置为高性能电源计划?Win2k8可能具有不同的默认值。默认情况下,许多服务器都不是这样,这会严重影响性能 OP确认这是根本原因
这是导致这种行为的一个有趣原因。当我做一些完全不同的事情时,这个想法闪现在我的脑海中。我在这里添加了这个额外的“答案”信息,而不是将其隐藏在我过长的作品中。@usr为我指出了电源管理选项建议的正确方向。OP中的人为测试以及原始问题都涉及不同线程之间的大量握手。在现实世界的应用程序中,握手是跨不同的进程进行的,但测试表明,如果是线程或进程进行握手,结果不会有所不同。在Windows Server 2008 R2中,在CPU使用率较低(例如,5%到10%)的情况下运行时,电源设置似乎会极大地影响信号量(内核同步对象)在CPU之间的共享。我对这一点的理解完全基于测量和计时应用 A也谈到了这一点 测试设置 操作系统电源选项设置Windows Server 2008 R2的默认电源计划为“平衡”。将其更改为“高性能”选项对该测试的性能有很大帮助。特别是,“更改高级电源设置”下的一个指定设置似乎是关键设置。“高级设置”在“处理器电源管理”下有一个称为“最小处理器状态”的选项。平衡计划下的默认值似乎为5%。在我的测试中将其更改为100%是关键 B
#include <windows.h>
#include <stdio.h>
#include <time.h>
HANDLE gSema4;
int gIterations = 1000000;
DWORD WINAPI testthread( LPVOID tn )
{
int count = gIterations;
while ( count-- )
{
WaitForSingleObject( gSema4, INFINITE );
ReleaseSemaphore( gSema4, 1, NULL );
}
return 0;
}
int main( int argc, char* argv[] )
{
DWORD threadId;
clock_t ct;
HANDLE threads[2];
gSema4 = CreateSemaphore( NULL, 1, 1, NULL );
ct = clock();
threads[0] = CreateThread( NULL, 0, testthread, NULL, 0, &threadId );
threads[1] = CreateThread( NULL, 0, testthread, NULL, 0, &threadId );
WaitForMultipleObjects( 2, threads, TRUE, INFINITE );
printf( "Total time = %d\n", clock() - ct );
CloseHandle( gSema4 );
return 0;
}
+----------------+-----------+---------------+----------------+
| OS | 2 cpu sem | 1 cpu sem | 2 cpu spinlock |
+----------------+-----------+---------------+----------------+
| Windows 7 | 7115 ms | 1960 ms (3.6) | 504 ms (14.1) |
| Server 2008 R2 | 20640 ms | 2263 ms (9.1) | 866 ms (23.8) |
| Server 2003 | 3570 ms | 1766 ms (2.0) | 452 ms (7.9) |
+----------------+-----------+---------------+----------------+
╔════════════════╦═════════════╦═══════════════╦════════════╗
║ ║ (i)Balanced ║ (ii) HighPerf ║ (iii) BIOS ║
╠════════════════╬═════════════╬═══════════════╬════════════╣
║ (a) Simple ║ 21.4 s ║ 9.2 s ║ 4.0 s ║
║ (b) Real World ║ 9.3 s ║ 2.2 s ║ 1.7 s ║
╚════════════════╩═════════════╩═══════════════╩════════════╝