您的位置:首页 > 运维架构

mic openmp 求dijkstra

2015-06-28 22:04 330 查看
</pre><pre name="code" class="cpp">#include <stdio.h>
#include <iostream>
#include <memory.h>
#include <omp.h>

using namespace std;

#define NODENUM 264346
#define MAXNODENUM 1000000
#define MAXEDGENUM 4000000
#define THREADNUM 64
#define MAXINPUTLINE 512
#define s 0 // source

// Graph info
int f[MAXNODENUM]; // Distance to source
int route[MAXNODENUM]; //route store the route
int edge_l[MAXEDGENUM], edge_r[MAXEDGENUM], edge_dis[MAXEDGENUM]; // An edge's left and right endtime, and its distance
int ad_next[MAXEDGENUM], ad_head[MAXNODENUM]; // Use adjacency list to store graph. For each point, use a list to store its adjacent edges table.
//ad_head is the list's first element(edge id), ad_next is each element(edge id)'s next pointer.

int edge_cnt = 0; // Number of edges

// Computation share memory
int msg_head[2][THREADNUM][THREADNUM], msg_next[2][MAXEDGENUM]; // Use a list to store msgs sent to T_1 from T_2. T_0 is a rolling array flag for even or odd iteraion.
int haltflag = 0, swflag = 0; // switch flag sets which msg_head and msg_next array we are loading and saving now. 0/1 only.

// Others
FILE *fp; // Input file
char line[MAXINPUTLINE]; // Input line
int x,y,z; // Input tmp integer
double starttime, endtime; // Timer
int iterationcnt; // Times of iteration

int main(int argc, char** argv)
{
if((fp=fopen(argv[1],"r")) == NULL) { printf("Cannot open %s\n", argv[1]); return -1; }
memset(ad_head,0,sizeof(ad_head));

// Input
while (fgets(line, MAXINPUTLINE, fp))
{
if (line[0] == 'a')
sscanf(line+2, "%d %d %d", &x, &y, &z);

// Edge data
edge_r[++edge_cnt] = y;
edge_l[edge_cnt] = x;
edge_dis[edge_cnt] = z;

// Adjacent table data. Use a list to store a point's adjacent edges.
ad_next[edge_cnt] = ad_head[x];
ad_head[x] = edge_cnt;
}
printf("Input finished\n");
memset(f,0xFF,sizeof(f));
memset(msg_head,0,sizeof(msg_head));

// INITIALIZE
f[s] = 0; // Distance from source node is 0
int firstthread = s % THREADNUM;
for(int m = ad_head[s]; m != 0; m = ad_next[m]) // Traverse all adjacent edges of the source node
{
int x = edge_r[m] % THREADNUM; // The edge's other end's thread
// Use a list to store msgs sent to x from firstthread.
msg_next[swflag][m] = msg_head[swflag][x][firstthread];
msg_head[swflag][x][firstthread] = m;
}

haltflag = 0; swflag = 1; iterationcnt = 0;
// START DIJKSTRA
starttime = omp_get_wtime();
#pragma omp parallel num_threads(THREADNUM)
{
int tid = omp_get_thread_num();
int tmp_edge,updatenum;

while(haltflag == 0) // When haltflag == 0, go on.
{
#pragma omp barrier
#pragma omp master
{
iterationcnt++; // Count iteration times for result show.
haltflag = 1; // Set haltflag to 1.
swflag = 1 - swflag; // Change iteration switch flag.
}
#pragma omp barrier
updatenum = 0;
for(int i = 0; i < THREADNUM; i++) // Each thread check other thread's update
{
tmp_edge = msg_head[swflag][tid][i]; // Updated edge from msg sent from i to me.
while(tmp_edge != 0)
{
int tmp_r = edge_r[tmp_edge];
int tmp_l = edge_l[tmp_edge];
if((f[tmp_r] == -1) || (f[tmp_r] > edge_dis[tmp_edge] + f[tmp_l])) // Better?
{
f[tmp_r] = edge_dis[tmp_edge] + f[tmp_l];

// Send msg to affected threads!
for(int m = ad_head[tmp_r]; m != 0; m = ad_next[m])
{
if(f[edge_r[m]] == -1 || f[edge_r[m]] > f[tmp_r] + edge_dis[m]) // better?
{
int x = edge_r[m] % THREADNUM;
msg_next[1-swflag][m] = msg_head[1-swflag][x][tid]; // Put into the msg list(next)
msg_head[1-swflag][x][tid] = m; // Msg list(head)
}
}
}
haltflag = 0; // Don't halt
tmp_edge = msg_next[swflag][tmp_edge]; // List iterate: element = element's next
}
}

#pragma omp barrier
for(int i = 0; i < THREADNUM; i++)
{
msg_head[swflag][tid][i] = 0; //Clear last msg
}
}
}
// Show result time
endtime = omp_get_wtime();
printf("data processed, loop for %d times\n",iterationcnt);
printf("Lost time: %.3lfs\n", endtime-starttime);

fclose(fp);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: