- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我在boost::smart_ptr
中找到了以下自旋锁代码:
bool try_lock()
{
return (__sync_lock_test_and_set(&v_, 1) == 0);
}
void lock()
{
for (unsigned k=0; !try_lock(); ++k)
{
if (k<4)
; // spin
else if (k < 16)
__asm__ __volatile__("pause"); // was ("rep; nop" ::: "memory")
else if (k < 32 || k & 1)
sched_yield();
else
{
struct timespec rqtp;
rqtp.tv_sec = 0;
rqtp.tv_nsec = 100;
nanosleep(&rqtp, 0);
}
}
}
void unlock()
{
__sync_lock_release(&v_);
}
因此,如果我理解正确的话,当锁被争用时,传入线程将呈指数级后退,首先疯狂旋转,然后暂停,然后放弃其时间片的剩余部分,最后在休眠和放弃之间来回切换。
我还找到了 glibc pthread_spinlock
实现,它使用汇编来执行锁。
#define LOCK_PREFIX "lock;" // using an SMP machine
int pthread_spin_lock(pthread_spinlock_t *lock)
{
__asm__ ("\n"
"1:\t" LOCK_PREFIX "decl %0\n\t"
"jne 2f\n\t"
".subsection 1\n\t"
".align 16\n"
"2:\trep; nop\n\t"
"cmpl $0, %0\n\t"
"jg 1b\n\t"
"jmp 2b\n\t"
".previous"
: "=m" (*lock)
: "m" (*lock));
return 0;
}
我承认我对汇编的理解不是很好,所以我不完全理解这里发生了什么。 (有人可以解释一下这是做什么的吗?)
但是,我对 boost 自旋锁和 glibc pthread_spinlock 进行了一些测试,当内核数多于线程数时,boost 代码的性能优于 glibc 代码。
另一方面,当线程数多于内核时,glibc 代码会更好。
这是为什么?这两种自旋锁实现之间的区别是什么,这使得它们在每种情况下都有不同的表现?
最佳答案
问题中发布的 pthread_spin_lock()
实现是从哪里获得的?它似乎缺少几行重要的代码。
我看到的实现(不是内联汇编 - 它是来自 glibc/nptl/sysdeps/i386/pthread_spin_lock.S
的独立汇编源文件)看起来很相似,但有两个额外的关键说明:
#include <lowlevellock.h>
.globl pthread_spin_lock
.type pthread_spin_lock,@function
.align 16
pthread_spin_lock:
mov 4(%esp), %eax
1: LOCK
decl 0(%eax)
jne 2f
xor %eax, %eax
ret
.align 16
2: rep
nop
cmpl $0, 0(%eax)
jg 1b
jmp 2b
.size pthread_spin_lock,.-pthread_spin_lock
它递减传入参数指向的long
,如果结果为零则返回。
否则,结果为非零,这意味着该线程没有获得锁。所以它执行了一个rep nop
,相当于pause
指令。这是一个“特殊”nop,它向 CPU 提示线程处于自旋状态,并且 cpu 应该以某种方式处理内存排序和/或分支预测,以提高这些情况下的性能(我不假装准确了解芯片外壳下发生的不同情况 - 从软件的角度来看,这与普通的旧 nop
没有区别。
在 pause
之后,它再次检查该值 - 如果它大于零,则锁未被认领,因此它跳转到函数的顶部并尝试再次认领锁。否则,它会再次跳转到 pause
。
这个自旋锁和 Boost 版本之间的主要区别在于,这个自旋锁在自旋时不会做任何比 pause
更有趣的事情——没有什么比 sched_yield()
或纳米 sleep ()
。所以线程保持热。我不确定这在你注意到的两种行为中究竟是如何发挥作用的,但是 glibc 代码会更贪婪——如果一个线程在锁上旋转并且有其他线程准备运行但没有可用的核心,旋转线程不会'不会帮助等待的线程获得任何 CPU 时间,而 Boost 版本最终会自动为等待某些关注的线程让路。
关于c++ - pthread_spinlock 和 boost::smart_ptr::spinlock 之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11111720/
我需要修复 getLineNumberFor 方法,以便如果 lastName 的第一个字符位于 A 和 M 之间,则返回 1;如果它位于 N 和 Z 之间,则返回 2。 在我看来听起来很简单,但我不
您好,感谢您的帮助!我有这个: 0 我必须在每次点击后增加“pinli
Javascript 中是否有一种方法可以在不使用 if 语句的情况下通过 switch case 结构将一个整数与另一个整数进行比较? 例如。 switch(integer) { case
我有一列是“日期”类型的。如何在自定义选项中使用“之间”选项? 最佳答案 请注意,您有2个盒子。 between(在SQL中)包含所有内容,因此将框1设置为:DATE >= startdate,将框2
我有一个表,其中包含年、月和一些数字列 Year Month Total 2011 10 100 2011 11 150 2011 12 100 20
这个问题已经有答案了: Extract a substring between double quotes with regular expression in Java (2 个回答) how to
我有一个带有类别的边栏。正如你在这里看到的:http://kees.een-site-bouwen.nl/ url 中类别的 ID。带有 uri 段(3)当您单击其中一个类别时,例如网页设计。显示了一
这个问题在这里已经有了答案: My regex is matching too much. How do I make it stop? [duplicate] (5 个答案) 关闭 4 年前。 我
我很不会写正则表达式。 我正在尝试获取括号“()”之间的值。像下面这样的东西...... $a = "POLYGON((1 1,2 2,3 3,1 1))"; preg_match_all("/\((
我必须添加一个叠加层 (ImageView),以便它稍微移动到包含布局的左边界的左侧。 执行此操作的最佳方法是什么? 尝试了一些简单的方法,比如将 ImageView 放在布局中并使用负边距 andr
Rx 中是否有一些扩展方法来完成下面的场景? 我有一个开始泵送的值(绿色圆圈)和其他停止泵送的值(簧片圆圈),蓝色圆圈应该是预期值,我不希望这个命令被取消并重新创建(即“TakeUntil”和“Ski
我有一个看起来像这样的数据框(Dataframe X): id number found 1 5225 NA 2 2222 NA 3 3121 NA 我有另一个看起来
所以,我正在尝试制作正则表达式,它将解析存储在对象中的所有全局函数声明,例如,像这样 const a = () => {} 我做了这样的事情: /(?:const|let|var)\s*([A-z0-
我正在尝试从 Intellivision 重新创建 Astro-Smash,我想让桶保持在两个 Angular 之间。我只是想不出在哪里以及如何让这个东西停留在两者之间。 我已经以各种方式交换了函数,
到处检查但找不到答案。 我有这个页面,我使用 INNER JOIN 将两个表连接在一起,获取它们的值并显示它们。我有这个表格,用来获取变量(例如开始日期、结束日期和卡号),这些变量将作为从表中调用值的
我陷入了两个不同的问题/错误之间,无法想出一个合适的解决方案。任何帮助将不胜感激 上下文、FFI 和调用大量 C 函数,并将 C 类型包装在 rust 结构中。 第一个问题是ICE: this pat
我在 MySQL 中有一个用户列表,在订阅时,时间戳是使用 CURRENT_TIMESTAMP 在数据库中设置的。 现在我想从此表中选择订阅日期介于第 X 天和第 Y 天之间的表我尝试了几个查询,但不
我的输入是开始日期和结束日期。我想检查它是在 12 月 1 日到 3 月 31 日之间。(年份可以更改,并且只有在此期间内或之外的日期)。 到目前为止,我还没有找到任何关于 Joda-time 的解决
我正在努力了解线程与 CPU 使用率的关系。有很多关于线程与多处理的讨论(一个很好的概述是 this answer )所以我决定通过在运行 Windows 10、Python 3.4 的 8 CPU
我正在尝试编写 PHP 代码来循环遍历数组以创建 HTML 表格。我一直在尝试做类似的事情: fetchAll(PDO::FETCH_ASSOC); ?>
我是一名优秀的程序员,十分优秀!