本代码主题借鉴nju的jyy老师的代码
自己增加了随机生成DAG(有向无环图)(不保证连通)数据进行测试
运行打印结果即为并行计算DAG的拓扑序
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>#define P(x) sem_wait(x)
#define V(x) sem_post(x)const int N = 7;
struct Edge {int from, to;sem_t sem;// 初始信号量值为0(使用c++标准库的信号量不能设置值为0)Edge(int f, int t) : from(f), to(t) {sem_init(&sem, 0, 0);}
};
std::vector<Edge> edges;
/*** 模拟计算任务* 一格计算任务可能需要其它计算结点的计算结果, * 又可能为其它计算结点提供自己的结果
*/
void* T_worker(void* arg) {int id = *((int *)arg);for (auto &edge : edges) {if (edge.to == id) {// id 为edge的入点// 意味着id需要等这个edge的出点发出信号P(&edge.sem);}}printf("Start %d\n", id);// 模拟计算过程sleep(1);printf("End %d\n", id);for (auto &edge : edges) {if (edge.from == id) {// id是edge的出边, 表示id要释放这个边的信号量V(&edge.sem);}}}
/*** 随机生成一个DAG
*/
void init_data() {// 随机一个拓扑序std::vector<int> vertices(N);for (int i = 0; i < N; ++i) {vertices[i] = i + 1;}std::random_device rd;std::mt19937 gen(rd());std::shuffle(vertices.begin(), vertices.end(), gen);// 序号小的随机向序号大的结点连边for (int i = 0; i < N; ++i) {for (int j = i + 1; j < N; ++j) {// 随机生成边if (gen() % 3 == 0) { edges.push_back(Edge(vertices[i], vertices[j]));}}}printf("graph:\n");for (const auto& edge : edges) {std::cout << edge.from << " -> " << edge.to << std::endl;}
}
int main() {std::vector<pthread_t> threads(N);std::vector<int> pid(N);init_data();for (int i = 0; i < N; i++) {pid[i] = i + 1;pthread_create(&threads[i], nullptr, &T_worker, &pid[i]);}for (int i = 0; i < N; i++) {pthread_join(threads[i], nullptr);}
}