int vertex_callback::invoke(io_request *reqs[], int num) { worker_thread *curr_thread = (worker_thread *) thread::get_curr_thread(); for (int i = 0; i < num; i++) { char *req_buf = reqs[i]->get_buf(); size_t req_size = reqs[i]->get_size(); assert(this->io == reqs[i]->get_io()); ext_mem_vertex ext_v(req_buf, req_size, graph->is_directed()); // If the algorithm doesn't need to get the full information // of their neighbors if (graph->get_required_neighbor_type() == edge_type::NONE // Or the vertex doesn't have neighbors. || (reqs[i]->get_user_data() == NULL && ext_v.get_num_edges(graph->get_required_neighbor_type()) == 0)) { // We can run user's code immediately on the vertex. compute_vertex &v = graph->get_vertex(ext_v.get_id()); v.materialize(ext_v); v.run(*graph, NULL, 0); v.dematerialize(); delete [] req_buf; } // We just fetched a vertex, we need to fetch its neighbors to // perform computation. else if (reqs[i]->get_user_data() == NULL) { curr_thread->add_pending_vertex(ext_v); } else { // Now a neighbor has been fetched, now we can do some computation // between the original pending vertex and its neighbor. pending_vertex *pending = (pending_vertex *) reqs[i]->get_user_data(); compute_vertex &v = graph->get_vertex( pending->get_id()); // We materialize the vertex and perform computation. // The callback function is guaranteed to be called in the thread // where a request is issued. Since all requests of fetching // neighbors are issued by one thread, we don't need to use a lock // to protect the pending vertex from concurrent access. v.materialize(*pending); v.run(*graph, &ext_v, 1); v.dematerialize(); // The buffer contains the info of the neighbor, no we don't need // it any more. delete [] req_buf; pending->complete_neighbor(); // Once we perform computation on all neighbors. We can destroy // the pending vertex. if (pending->is_complete()) pending_vertex::destroy(pending); } } return 0; }
static bool rt_valid(DstBlock& dst, SrcBlock const& src) { VBlock const& vblock = src.get_vblk(); MBlock const& mblock = src.get_mblk(); Ext_data<DstBlock, dst_lp> ext_dst(dst, SYNC_OUT); Ext_data<VBlock, vblock_lp> ext_v(vblock, SYNC_IN); Ext_data<MBlock, mblock_lp> ext_m(mblock, SYNC_IN); if (SD == row && Type_equal<order_type, row2_type>::value || SD == col && Type_equal<order_type, col2_type>::value) { dimension_type const axis = SD == row ? 1 : 0; length_type dst_stride = static_cast<length_type>(abs(ext_dst.stride(axis == 0))); length_type m_stride = static_cast<length_type>(abs(ext_m.stride(axis == 0))); return // make sure blocks are dense (major stride == minor size) (ext_dst.size(axis) == dst_stride) && (ext_m.size(axis) == m_stride) && // ensure unit stride along the dimension opposite the chosen one (ext_dst.stride(axis) == 1) && (ext_m.stride(axis) == 1) && (ext_v.stride(0) == 1); } else { dimension_type const axis = SD == row ? 0 : 1; length_type dst_stride = static_cast<length_type>(abs(ext_dst.stride(axis == 0))); length_type m_stride = static_cast<length_type>(abs(ext_m.stride(axis == 0))); return // make sure blocks are dense (major stride == minor size) (ext_dst.size(axis) == dst_stride) && (ext_m.size(axis) == m_stride) && // ensure unit stride along the same dimension as the chosen one (ext_dst.stride(axis) == 1) && (ext_m.stride(axis) == 1) && (ext_v.stride(0) == 1); } }