这是我为一个操作系统课的作业写的,我已经完成并交了。我昨天发布了这个问题,但由于“学术诚信”的规定,我把它关闭,直到提交截止日期后。
目的是学习如何使用临界区。有一个data
数组,其中有100个单调递增的数字,0...99和40个线程,每个线程随机交换两个元素2,000,000次。每秒一次Checker
通过,并确保每个数字只有一个(这意味着没有发生并行访问)。
以下是Linux时代:
real 0m5.102s
user 0m5.087s
sys 0m0.000s
OS X时代
real 6m54.139s
user 0m41.873s
sys 6m43.792s
我在运行OS X的同一台机器上运行一个带有ubuntu/trusty64
的vagrant box。这是一个四核i7 2.3Ghz(高达3.2Ghz)2012 rMBP。
如果我理解正确的话,sys
是系统开销,我无法控制,即使这样,41秒的用户时间也表明线程可能是串行运行的。
如果需要,我可以发布所有代码,但我会发布我认为相关的位。我使用pthreads
,因为这是Linux提供的,但我假设它们在OSX上工作。
创建swapper
线程以运行swapManyTimes
例程:
for (int i = 0; i < NUM_THREADS; i++) {
int err = pthread_create(&(threads[i]), NULL, swapManyTimes, NULL);
}
Swapper
线程临界区,在for循环中运行200万次:
pthread_mutex_lock(&mutex); // begin critical section
int tmpFirst = data[first];
data[first] = data[second];
data[second] = tmpFirst;
pthread_mutex_unlock(&mutex); // end critical section
只创建一个Checker
线程,与Swapper
相同。它通过遍历data
数组并用true
标记与每个值对应的索引来操作。然后,它检查有多少索引是空的。例如:
pthread_mutex_lock(&mutex);
for (int i = 0; i < DATA_SIZE; i++) {
int value = data[i];
consistency[value] = 1;
}
pthread_mutex_unlock(&mutex);
它在运行完while(1)
循环后,通过调用sleep(1)
每秒运行一次。在所有swapper
线程都被加入后,这个线程也被取消并加入。
我很乐意提供任何更多的信息,可以帮助弄清楚为什么这在Mac上这么糟糕。我并不是真的在寻求代码优化方面的帮助,除非这是OSX的问题。我尝试在OS X上同时使用clang
和gcc-4.9
构建它。
4条答案
按热度按时间a6b3iqyw1#
MacOSX和Linux实现pthread的方式不同,导致了这种缓慢的行为。特别是MacOSX不使用自旋锁(根据ISO C标准,它们是可选的)。这可能会导致像这样的示例的代码性能非常非常慢。
k3bvogb12#
我已经在很大程度上复制了你的结果(没有扫地机):
在Linux(2.6.18-308.24.1.el5)服务器上Intel(R)Xeon(R)CPU E3-1230 V2@3.30GHz
在我的MacBook Pro(约塞米蒂10.10.2)2.6 GHz i7,16 GB内存
我的Mac用了12倍的挂钟时间来完成40个线程,这是相对于一个非常旧的Linux + gcc版本。
注意:我更改了代码,使每个线程可以执行1 M次交换。
看起来在争论之下,OSX比Linux做了更多的工作。也许它比Linux更精细地交织它们?
EDIT更新代码,记录线程立即重新捕获锁的平均次数:
Linux
Mac OSX
因此,OSX更均匀地共享其锁,因此有更多的线程挂起和恢复。
tyky79it3#
因此,单个线程可以很好地获得CPU,并且直到它完成所有2 mil执行才释放它。
这将导致在linux上执行上下文切换的时间最少。
然而,在MAC OS上,在允许另一个“准备执行”线程/进程执行之前,执行仅被给予“时间片”来执行。
这意味着更多的上下文切换。
上下文切换在“sys”时间内执行。
结果是MAC OS将需要更长的时间来执行。
为了平衡环境,可以通过插入一个nanosleep()或调用
gcmastyq4#
只是碰到了这个问题。8年过去了,OS X和MacBook现在使用苹果硅M2芯片。我编译了上面发布的程序,并用
cc -O2 thread1.cc -o thread1
编译。这台机器是2023 MBP w/Apple M2 Max芯片。12核,3.49GHz,无超线程。64GB RAM。OS X Ventura 13.2。
编译器是:
结果如下:
旧OSX
所以基本上快了100倍。下面是40线程运行:
非常快!然后我在一个新的AWS Linux c5.4xlarge示例上尝试了它:
编译:
得到这个结果:
因此,新的Linux/16 proc机器比“旧”Linux * 慢 *。真有趣感谢@jschultz410发布了这样一段紧凑且高度可移植的C代码。