- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试用 C 语言实现 Lamport 烘焙算法的简化版本,然后再尝试使用它来解决更复杂的问题。*我所做的简化是锁仅由两个线程共享,而不是由两个线程共享。 N.
我设置了两个线程(通过 OpenMP 以保持简单),它们循环,尝试增加其关键部分内的共享计数器。如果一切按计划进行,那么最终的计数器值应该等于迭代次数。但是,这里有一些示例输出:
count: 9371470 (expected: 10000000)
哦!有些东西坏了,但是什么?我的实现非常像教科书( for reference ),所以也许我滥用了内存屏障?我是否忘记将某些内容标记为 volatile ?
我的代码:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <omp.h>
typedef struct
{
volatile bool entering[2];
volatile uint32_t number[2];
} SimpleBakeryLock_t;
inline void mb() { __sync_synchronize(); }
inline void lock(SimpleBakeryLock_t* l, int id)
{
int i = id, j = !id;
uint32_t ni, nj;
l->entering[i] = true;
mb();
ni = 1 + l->number[j];
l->number[i] = ni;
mb();
l->entering[i] = false;
mb();
while (l->entering[j]) {
mb();
}
nj = l->number[j];
mb();
while ((nj != 0) && (nj < ni || (nj == ni && j < i)))
{
nj = l->number[j]; // re-read
mb();
}
}
inline void unlock(SimpleBakeryLock_t* l, int id)
{
l->number[id] = 0;
mb();
}
SimpleBakeryLock_t x;
int main(void)
{
const uint32_t iterations = 10000000;
uint32_t count = 0;
bool once = false;
int i;
memset((void*)&x, 0, sizeof(x));
mb();
// set OMP_NUM_THREADS=2 in your environment!
#pragma omp parallel for schedule(static, 1) private(once, i)
for(uint32_t dummy = 0; dummy < iterations; ++dummy)
{
if (!once)
{
i = omp_get_thread_num();
once = true;
}
lock(&x, i);
{
count = count + 1;
mb();
}
unlock(&x, i);
}
printf("count: %u (expected: %u)\n", count, iterations);
return 0;
}
要编译并运行(在 Linux 上),请执行以下操作:
$ gcc -O3 -fopenmp bakery.c
$ export OMP_NUM_THREADS=2
$ ./a.out
最佳答案
我找到了两个问题,代码现在可以工作了。问题:
为了完整性,以下是更正后的代码:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <omp.h>
#define cpu_relax() asm volatile ("pause":::"memory")
#define mb() asm volatile ("mfence":::"memory")
/* Simple Lamport bakery lock for two threads. */
typedef struct
{
volatile uint32_t entering[2];
volatile uint32_t number[2];
} SimpleBakeryLock_t;
void lock(SimpleBakeryLock_t* l, int id)
{
int i = id, j = !id;
uint32_t ni, nj;
l->entering[i] = 1;
mb();
ni = 1 + l->number[j];
l->number[i] = ni;
mb();
l->entering[i] = 0;
mb();
while (l->entering[j]) {
cpu_relax();
}
do {
nj = l->number[j];
} while ((nj != 0) && (nj < ni || (nj == ni && j < i)));
}
void unlock(SimpleBakeryLock_t* l, int id)
{
mb(); /* prevent critical section writes from leaking out over unlock */
l->number[id] = 0;
mb();
}
SimpleBakeryLock_t x;
int main(void)
{
const int32_t iterations = 10000000;
int32_t dummy;
uint32_t count = 0;
memset((void*)&x, 0, sizeof(x));
mb();
// set OMP_NUM_THREADS=2 in your environment!
#pragma omp parallel for schedule(static, 1)
for(dummy = 0; dummy < iterations; ++dummy)
{
int i = omp_get_thread_num();
lock(&x, i);
count = count + 1;
unlock(&x, i);
}
printf("count: %u (expected: %u)\n", count, iterations);
return 0;
}
关于c - 用 C 语言调试 Lamport 烘焙算法的简化版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16868673/
do { choosing[i] = true; number[i] = max(number[0], number[1], …, number [n – 1])+1; ch
我目前正在尝试了解 Lamport 时间戳。考虑两个进程 P1 (产生事件 a1 、 a2 、...)和 P2 (产生事件 b1 , b2 ,...)。让 C(e) 表示与事件相关的 Lamport
我知道每个进程都有一个逻辑时钟 C,a->b 如果 C(a) < C(b)。但是他们如何启动这些流程呢?这里我们有一张图片: 他们使用消息传递吗?我们从进程 P1 开始,它向 P2 发送消息?那么P2
由于这是一篇著名的计算机科学论文,我决定阅读 Lamport 的 Time, Clocks, and the Ordering of Events in a Distributed System .除
Phase 2. (a) If the proposer receives a response to its prepare requests (numbered n) from a majorit
JLS-17.4.3定义每个线程的程序顺序,其中线程程序内的任何重新排序都将保留线程内语义。然后它根据程序顺序定义顺序一致性。它说顺序一致性是与程序顺序一致的所有 Action 的总顺序。 现在我有一
我正在尝试用 C 语言实现 Lamport 烘焙算法的简化版本,然后再尝试使用它来解决更复杂的问题。*我所做的简化是锁仅由两个线程共享,而不是由两个线程共享。 N. 我设置了两个线程(通过 OpenM
据我所知,lamport 时间戳是一种用于确保跨多个站点的事件具有部分顺序的工具。 From wikipedia : In pseudocode, the algorithm for sending
我正在实现 Lamport's bakery algorithm . 我的输出显示线程 1 和 2 的优先级高于其他线程。我的实现如下。 #include(pthread.h) #include(st
我是一名优秀的程序员,十分优秀!