void multiply(DistSlicedMat & mat, int curoffset, double a){ assert(a>0); DistVec current = mat[curoffset]; assert(mat.start_offset <= current.offset); vec result = zeros(curoffset); if (curoffset > 0){ #pragma omp parallel for for (int i=mat.start_offset; i< current.offset; i++){ for (int k=info.get_start_node(!current.transpose); k< info.get_end_node(!current.transpose); k++){ result[i-mat.start_offset] += latent_factors_inmem[k].pvec[i] * latent_factors_inmem[k].pvec[current.offset]; } } #pragma omp parallel for for (int k=info.get_start_node(!current.transpose); k< info.get_end_node(!current.transpose); k++){ latent_factors_inmem[k].pvec[curoffset] /= a; } for (int i=mat.start_offset; i< current.offset; i++){ #pragma omp parallel for for (int k=info.get_start_node(!current.transpose); k< info.get_end_node(!current.transpose); k++){ latent_factors_inmem[k].pvec[current.offset] -= result[i-mat.start_offset]/a * latent_factors_inmem[k].pvec[i]; } } } current.debug_print(current.name); }
void orthogonalize_vs_all(DistSlicedMat & mat, int curoffset, double &alpha){ assert(mi.ortho_repeats >=1 && mi.ortho_repeats <= 3); bool old_debug = debug; debug = false; DistVec current = mat[curoffset]; assert(mat.start_offset <= current.offset); double * alphas = new double[curoffset]; //DistDouble * alphas = new DistDouble[curoffset]; //cout<<current.to_vec().transpose() << endl; if (curoffset > 0){ for (int j=0; j < mi.ortho_repeats; j++){ memset(alphas, 0, sizeof(double)*curoffset); #pragma omp parallel for for (int i=mat.start_offset; i< current.offset; i++){ for (int k=info.get_start_node(!current.transpose); k< info.get_end_node(!current.transpose); k++){ assert(i-mat.start_offset>=0 && i-mat.start_offset < curoffset); assert(i < latent_factors_inmem[k].pvec.size()); assert(k < (int)latent_factors_inmem.size()); assert(current.offset < latent_factors_inmem[k].pvec.size()); alphas[i-mat.start_offset] += latent_factors_inmem[k].pvec[i] * latent_factors_inmem[k].pvec[current.offset]; } } for (int i=mat.start_offset; i< current.offset; i++){ #pragma omp parallel for for (int k=info.get_start_node(!current.transpose); k< info.get_end_node(!current.transpose); k++){ latent_factors_inmem[k].pvec[current.offset] -= alphas[i-mat.start_offset] * latent_factors_inmem[k].pvec[i]; } } } //for ortho_repeast } delete [] alphas; debug = old_debug; current.debug_print(current.name); // alpha = 0; double sum = 0; int k; //#pragma omp parallel for private(k) reduction(+: sum) for (k=info.get_start_node(!current.transpose); k< info.get_end_node(!current.transpose); k++){ sum = sum + pow(latent_factors_inmem[k].pvec[current.offset],2); } alpha = sqrt(sum); if (alpha >= 1e-10 ){ #pragma omp parallel for for (int k=info.get_start_node(!current.transpose); k< info.get_end_node(!current.transpose); k++){ latent_factors_inmem[k].pvec[current.offset]/=alpha; } } }
/** * Vertex update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { if (vertex.id() < (uint)mi.start || vertex.id() >= (uint)mi.end) return; vertex_data& user = latent_factors_inmem[vertex.id()]; bool rows = vertex.id() < (uint)info.get_start_node(false); if (info.is_square()) rows = mi.A_transpose; (void) rows; // unused assert(mi.r_offset >=0); //store previous value for convergence detection if (mi.prev_offset >= 0) user.pvec[mi.prev_offset ] = user.pvec[mi.r_offset]; double val = 0; assert(mi.x_offset >=0 || mi.y_offset>=0); /*** COMPUTE r = c*A*x ********/ if (mi.A_offset && mi.x_offset >= 0){ for(int e=0; e < vertex.num_edges(); e++) { const edge_data & edge = vertex.edge(e)->get_data(); const vertex_data & movie = latent_factors_inmem[vertex.edge(e)->vertex_id()]; val += (edge.weight * movie.pvec[mi.x_offset]); } if (info.is_square() && mi.use_diag)// add the diagonal term val += (/*mi.c**/ (user.A_ii+ regularization) * user.pvec[mi.x_offset]); val *= mi.c; } /***** COMPUTE r = c*I*x *****/ else if (!mi.A_offset && mi.x_offset >= 0){ val = mi.c*user.pvec[mi.x_offset]; } /**** COMPUTE r+= d*y (optional) ***/ if (mi.y_offset>= 0){ val += mi.d*user.pvec[mi.y_offset]; } /***** compute r = (... ) / div */ if (mi.div_offset >= 0){ val /= user.pvec[mi.div_offset]; } assert(mi.r_offset>=0 && mi.r_offset < user.pvec.size()); user.pvec[mi.r_offset] = val; } //end update
DistVec& DistVec::operator=(DistMat &mat){ mi.r_offset = offset; assert(prev_offset < data_size); mi.prev_offset = prev_offset; transpose = mat.transpose; mi.start = info.get_start_node(!transpose); mi.end = info.get_end_node(!transpose); //graphchi_engine<VertexDataType, EdgeDataType> engine(training, nshards, false, m); //set_engine_flags(engine); //Axb program; pengine->run(program, 1); debug_print(name); mi.reset_offsets(); mat.transpose = false; return *this; }
DistVec& DistVec::operator=(DistMat &mat){ mi.r_offset = offset; assert(prev_offset < data_size); mi.prev_offset = prev_offset; transpose = mat.transpose; mi.start = info.get_start_node(!transpose); mi.end = info.get_end_node(!transpose); graphchi_engine<VertexDataType, EdgeDataType> engine(training, nshards, false, m); engine.set_disable_vertexdata_storage(); Axb program; engine.set_modifies_inedges(false); engine.set_modifies_outedges(false); engine.run(program, 1); debug_print(name); mi.reset_offsets(); mat.transpose = false; return *this; }
/* Gather the weighted rank of the adjacent page */ double gather(icontext_type& context, const vertex_type& vertex, edge_type& edge) const { if (edge.data().role == edge_data::PREDICT) return 0; bool brows = vertex.id() < (uint)info.get_start_node(false); if (info.is_square()) brows = !mi.A_transpose; if (mi.A_offset && mi.x_offset >= 0){ double val = edge.data().obs * (brows ? edge.target().data().pvec[mi.x_offset] : edge.source().data().pvec[mi.x_offset]); //printf("gather edge on vertex %d val %lg obs %lg\n", vertex.id(), val, edge.data().obs); return val; } //printf("edge on vertex %d val %lg\n", vertex.id(), 0.0); return 0; }
DistVec& DistVec::operator=(DistMat &mat){ mi.r_offset = offset; assert(prev_offset < data_size); mi.prev_offset = prev_offset; transpose = mat.transpose; mi.start = info.get_start_node(!transpose); mi.end = info.get_end_node(!transpose); INITIALIZE_TRACER(Axbtrace, "Axb update function"); BEGIN_TRACEPOINT(Axbtrace); pcurrent = this; int old_start = start; int old_end = end; start = mi.start; end = mi.end; start_engine(); start = old_start; end = old_end; END_TRACEPOINT(Axbtrace); debug_print(name); mi.reset_offsets(); mat.transpose = false; return *this; }
void init(){ start = info.get_start_node(!transpose); end = info.get_end_node(!transpose); assert(start < end && start >= 0 && end >= 1); //debug_print(name); };
bool selected_node(const graph_type::vertex_type& vertex){ if (info.is_square()) return true; else return ((vertex.id() >= (uint)info.get_start_node(!pcurrent->transpose)) && (vertex.id() < (uint)info.get_end_node(!pcurrent->transpose))); }