不透明函数调用在编译器优化中意味着什么?我在为什么全局变量会给函数调用中的编译器优化带来麻烦?,而“不透明函数调用”确实让我感到困惑。不透明函数调用似乎是编译器没有任何信息的函数调用。但是这是什么意思?
c compiler-construction concurrency multithreading lock-free
我想知道无锁编程相对于自旋锁有哪些优点?我认为当我们在一个线程(称为A)中使用CAS机制进行无锁编程时,如果其他线程更改了CAS中的值,A线程仍然需要再次循环。我认为这就像我们使用自旋锁一样!
我对此很困惑。虽然我知道CAS和spin-lock适合在锁争用不激烈的情况下使用,但是谁能解释一下在哪些场景下应该使用lock free,应该使用spin lock?
我想使用异步函数调用。我选择了boost::deadline_timer。
对我来说,硬件计时器是一种特定的硬件(令人惊讶),它独立于 CPU 工作,仅用于监视时间。同时,如果我理解正确,它也可以用于设置超时并在达到超时时产生中断。(计时器)
其主要优点是异步执行。设置定时器的线程可以继续工作,回调函数将在设置定时器的同一线程中触发。
让我描述一下我在行动中看到的情况。
应用程序包含一个或多个工作线程。例如,他们处理输入项目并过滤它们。让我们考虑应用程序有 5 个线程,每个线程设置一个计时器(5 秒)。
应用程序正在运行。例如当前线程是thread-3.
计时器 ( thread-0) 已到期并生成(可能是错误的术语)中断。
线程上下文切换 ( thread-3-> thread-0);
回调函数执行;
计时器 ( thread-1) 已到期并产生中断。
...
等等
PS0。我知道这不仅仅是多线程应用程序的一种可能情况。
问题:
我是否正确描述了工作过程?
难道我理解正确的话,即使当前线程是thread-0它也导致上下文切换,因为线程必须停止执行当前的代码,并切换到执行从回调机能的研究码?
如果每个线程设置 100k 或 500k 计时器,它将如何影响性能?
硬件是否有计时器计数的限制?
更新计时器的超时时间有多昂贵?
鉴于以下情况:
class Foo
{
public:
void Increment()
{
_InterlockedIncrement(&m_value); // OSIncrementAtomic
}
long GetValue()
{
return m_value;
}
private:
long m_value;
};
Run Code Online (Sandbox Code Playgroud)
读取时是否需要内存屏障m_value?我的理解是,这_InterlockedIncrement将生成完整的内存屏障,并确保在发生任何后续加载之前存储该值。因此,从这方面来看,这听起来很安全,但是,m_value完全可以缓存,即可以GetValue()返回陈旧的值,即使在原子递增时也是如此?
Jeff Preshing 的优秀文章供参考:https://preshing.com/20120515/memory-reordering-caught-in-the-act/
其他上下文:
我正在关注一系列有关无锁编程的文章,特别是查看变量的用法unfinishedJobs以及此处的潜在实现HasJobCompleted:
https: //blog.molecular-matters.com/2015/08 /24/job-system-2-0-lock-free-work-stealing-part-1-basics/
void Wait(const Job* job)
{
// wait until the job has completed. in the meantime, work on any other job.
while (!HasJobCompleted(job))
{
Job* nextJob = GetJob();
if (nextJob)
{
Execute(nextJob);
}
}
}
Run Code Online (Sandbox Code Playgroud)
可以通过将 unfinishedJobs …
是否有可能通过内存屏障实现易失性变量的相同“保证”(始终读/写内存而不是寄存器)?只需在一个线程中写入变量,然后在另一个线程中读取其值。下面的内容是等价的吗?
#define rmb() __sync_synchronize()
#define wmb() __sync_synchronize()
static volatile int a;
static int b;
//invoked by thread 1
static void writer(void)
{
...
a = 1;
...
b = 1;
wmb();
}
//invoked by thread 2
static void reader(void)
{
...
while (a != 1)
;
// do something
...
while (b != 1)
rmb();
// do something
}
Run Code Online (Sandbox Code Playgroud)
编辑:好的,我知道 volatile 不能保证原子性、可见性或顺序。内存屏障除了排序之外还提供其他功能吗?还有能见度?除了 _Atomic C11 或 gcc/clang 原子内置函数之外,还有其他东西可以保证可见性吗?
My test shows that using lock-free atomic fetch_add is much slower than using mutex. I am running 10 parallel threads adding 1 million to the shared counter each. I am using relaxed memory order. Did I do the atomic wrong?
output from test:
fetch_add elapsed time: 4.14048 secs
fetch_add elapsed time: 5.37776 secs
fetch_add elapsed time: 5.37771 secs
fetch_add elapsed time: 5.37791 secs
fetch_add elapsed time: 5.37865 secs
fetch_add elapsed time: 7.85113 secs
fetch_add elapsed time: 7.93542 secs
fetch_add elapsed …Run Code Online (Sandbox Code Playgroud)