Gemini代码摘抄(三)process_vertices
来源:互联网 发布:amds汽车材料数据系统 编辑:程序博客网 时间:2024/05/22 15:27
process_vertices函数
有两个参数:process和要处理的点集合
process_vertices(std::function<R(VertexId)> process, Bitmap * active) {}
其调用如下:
double delta = graph->process_vertices<double>( [&](VertexId vtx){ curr[vtx] = (double)1; if (graph->out_degree[vtx]>0) { curr[vtx] /= graph->out_degree[vtx]; } return (double)1; }, active_in );
函数体内部如下:
根据已有的threads和设置的threads_per_socket把线程划分到分区,s_i 是分区号,s_j socket内的线程编号
// process vertices template<typename R> R process_vertices(std::function<R(VertexId)> process, Bitmap * active) { double stream_time = 0; stream_time -= MPI_Wtime(); R reducer = 0; size_t basic_chunk = 64; for (int t_i=0;t_i<threads;t_i++) { int s_i = get_socket_id(t_i); int s_j = get_socket_offset(t_i);
计算分区大小partition_size,thread_state[t_i]->curr和thread_state[t_i]->end分别表示分区内每个线程t_i负责部分的首尾
VertexId partition_size = local_partition_offset[s_i+1] -local_partition_offset[s_i]; thread_state[t_i]->curr = local_partition_offset[s_i] + partition_size / threads_per_socket / basic_chunk * basic_chunk * s_j; thread_state[t_i]->end = local_partition_offset[s_i] + partition_size / threads_per_socket / basic_chunk * basic_chunk * (s_j+1);
如果一个分区规定的线程数已经满了,此时线程的尾就设置为下一分区的开始。把当前线程的状态设置为working,表示正在执行自己的任务。
if (s_j == threads_per_socket - 1) { thread_state[t_i]->end = local_partition_offset[s_i+1]; } thread_state[t_i]->status = WORKING; }
下列代码是并行执行的。
__sync_fetch_and_add相关介绍看这里
下面一段代码讲的是线程执行自己的任务。
把线程现在的位置赋给v_i然后curr往后移64位,一个基本块的大小,当v_i已经到end的时候就跳出循环,表示当前线程自己的工作已经完成了,该线程状态置为stealing,看看其他线程还有什么工作可以帮忙做的。
#pragma omp parallel reduction(+:reducer) { R local_reducer = 0; int thread_id = omp_get_thread_num(); while (true) { VertexId v_i = __sync_fetch_and_add(&thread_state[thread_id]->curr, basic_chunk); if (v_i >= thread_state[thread_id]->end) break;
下面这一段不是很懂
从v_i开始,做完一个往后移动一个,直到word为0
unsigned long word = active->data[WORD_OFFSET(v_i)]; while (word != 0) { if (word & 1) { local_reducer += process(v_i); } v_i++; word = word >> 1; } } thread_state[thread_id]->status = STEALING;
下面一段代码讲的是线程stealing任务做。
根据当前线程id计算一个线程id出来赋值给t_i,当线程t_i的状态处于stealing时,他就执行reduce
for (int t_offset=1;t_offset<threads;t_offset++) { int t_i = (thread_id + t_offset) % threads; while (thread_state[t_i]->status!=STEALING) { VertexId v_i = __sync_fetch_and_add(&thread_state[t_i]->curr, basic_chunk); if (v_i >= thread_state[t_i]->end) continue; unsigned long word = active->data[WORD_OFFSET(v_i)]; while (word != 0) { if (word & 1) { local_reducer += process(v_i); } v_i++; word = word >> 1; } } } reducer += local_reducer; }
以上都是并行执行的代码。
MPI_ALLreduce函数
相关MPI编程
R global_reducer; MPI_Datatype dt = get_mpi_data_type<R>(); MPI_Allreduce(&reducer, &global_reducer, 1, dt, MPI_SUM, MPI_COMM_WORLD); stream_time += MPI_Wtime(); #ifdef PRINT_DEBUG_MESSAGES if (partition_id==0) { printf("process_vertices took %lf (s)\n", stream_time); } #endif return global_reducer; }
MPI资料下载:http://micro.ustc.edu.cn/Linux/MPI/
阅读全文
0 0
- Gemini代码摘抄(三)process_vertices
- Gemini代码摘抄(四)process_edges
- Gemini代码摘抄(二)load_directed
- Gemini代码摘抄(一)Graph和init
- Gemini
- gloox代码分析 - 注册模块(摘抄)
- centos下运行Gemini(单机&分布式)
- hadoop摘抄(三)
- UILongPressGestureRecognizer代码摘抄
- 摘抄代码片段
- 如何阅读代码摘抄(not too good)
- O_NONBLOCK注意事项(摘抄自《代码的未来》)
- 实验书本上关于继承的代码(摘抄)
- 《黑客与画家》摘抄 三
- 幽默感悟(摘抄)
- 萨提亚亲密关系(摘抄)
- 俏皮箴言(摘抄)
- jdbc 入门(摘抄)
- 栈的基本操作
- 清华大学2006年机试-N的阶乘-1076
- AP和STA模式分别是什么意思
- 判断字符串是否为空的org.apache.commons.lang3.StringUtils类方法isBlank()源码查看
- 大数据是什么
- Gemini代码摘抄(三)process_vertices
- 海底捞将推鑫飞智能餐桌 再次颠覆餐饮业
- Android mainfest文件 android属性 汇总
- 约瑟夫问题
- 通过配置PIX防火墙实现FTP客户端对服务端的访问
- Linux----进程间的管道通信
- 安卓升级8.0后,再次带来新的黑科技,让你没想到是这个
- Set集合
- 【读书笔记:疯狂java讲义】java面向对象