void evaluateGeneric (tree *tr, nodeptr p, boolean fullTraversal) { /* now this may be the entry point of the library to compute the log like at a branch defined by p and p->back == q */ volatile double result = 0.0; nodeptr q = p->back; int i, model; /* set the first entry of the traversal descriptor to contain the indices of nodes p and q */ tr->td[0].ti[0].pNumber = p->number; tr->td[0].ti[0].qNumber = q->number; /* copy the branch lengths of the tree into the first entry of the traversal descriptor. if -M is not used tr->numBranches must be 1 */ for(i = 0; i < tr->numBranches; i++) tr->td[0].ti[0].qz[i] = q->z[i]; /* now compute how many conditionals must be re-computed/re-oriented by newview to be able to calculate the likelihood at the root defined by p and q. */ /* one entry in the traversal descriptor is already used, hence set the tarversal length counter to 1 */ tr->td[0].count = 1; /* do we need to recompute any of the vectors at or below p ? */ if(fullTraversal) { assert(isTip(p->number, tr->mxtips)); computeTraversalInfo(q, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, FALSE); } else { if(!p->x) computeTraversalInfo(p, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, TRUE); /* recompute/reorient any descriptors at or below q ? computeTraversalInfo computes and stores the newview() to be executed for the traversal descriptor */ if(!q->x) computeTraversalInfo(q, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, TRUE); } /* now we copy this partition execute mask into the traversal descriptor which must come from the calling program, the logic of this should not form part of the library */ storeExecuteMaskInTraversalDescriptor(tr); /* also store in the traversal descriptor that something has changed i.e., in the parallel case that the traversal descriptor list of nodes needs to be broadcast once again */ tr->td[0].traversalHasChanged = TRUE; evaluateIterative(tr); if(0) { double *recv = (double *)malloc(sizeof(double) * tr->NumberOfModels); MPI_Allreduce(tr->perPartitionLH, recv, tr->NumberOfModels, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); for(model = 0; model < tr->NumberOfModels; model++) { /* TODO ??? */ /*tr->perPartitionLH[model] = recv[model]; */ result += recv[model]; } rax_free(recv); } else { double *recv = (double *)malloc(sizeof(double) * tr->NumberOfModels); MPI_Reduce(tr->perPartitionLH, recv, tr->NumberOfModels, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Bcast(recv, tr->NumberOfModels, MPI_DOUBLE, 0, MPI_COMM_WORLD); for(model = 0; model < tr->NumberOfModels; model++) { /* TODO ??? */ tr->perPartitionLH[model] = recv[model]; result += recv[model]; } rax_free(recv); } /* set the tree data structure likelihood value to the total likelihood */ tr->likelihood = result; /* MPI_Barrier(MPI_COMM_WORLD); printf("Process %d likelihood: %f\n", processID, tr->likelihood); MPI_Barrier(MPI_COMM_WORLD); */ /* do some bookkeeping to have traversalHasChanged in a consistent state */ tr->td[0].traversalHasChanged = FALSE; }
void evaluateGeneric (tree *tr, nodeptr p, boolean fullTraversal) { /* now this may be the entry point of the library to compute the log like at a branch defined by p and p->back == q */ volatile double result = 0.0; nodeptr q = p->back; int i, model; boolean p_recom = FALSE, /* if one of was missing, we will need to force recomputation */ q_recom = FALSE; /* set the first entry of the traversal descriptor to contain the indices of nodes p and q */ tr->td[0].ti[0].pNumber = p->number; tr->td[0].ti[0].qNumber = q->number; /* copy the branch lengths of the tree into the first entry of the traversal descriptor. if -M is not used tr->numBranches must be 1 */ for(i = 0; i < tr->numBranches; i++) tr->td[0].ti[0].qz[i] = q->z[i]; /* recom part */ if(tr->useRecom) { int slot = -1; if(!isTip(q->number, tr->mxtips)) { q_recom = getxVector(tr->rvec, q->number, &slot, tr->mxtips); tr->td[0].ti[0].slot_q = slot; } if(!isTip(p->number, tr->mxtips)) { p_recom = getxVector(tr->rvec, p->number, &slot, tr->mxtips); tr->td[0].ti[0].slot_p = slot; } if(!isTip(p->number, tr->mxtips) && !isTip(q->number, tr->mxtips)) assert(tr->td[0].ti[0].slot_q != tr->td[0].ti[0].slot_p); } /* now compute how many conditionals must be re-computed/re-oriented by newview to be able to calculate the likelihood at the root defined by p and q. */ /* one entry in the traversal descriptor is already used, hence set the tarversal length counter to 1 */ tr->td[0].count = 1; if(fullTraversal) { assert(isTip(q->back->number, tr->mxtips)); computeTraversal(tr, q, FALSE); } else { if(p_recom || needsRecomp(tr->useRecom, tr->rvec, p, tr->mxtips)) computeTraversal(tr, p, TRUE); if(q_recom || needsRecomp(tr->useRecom, tr->rvec, q, tr->mxtips)) computeTraversal(tr, q, TRUE); } /* now we copy this partition execute mask into the traversal descriptor which must come from the calling program, the logic of this should not form part of the library */ storeExecuteMaskInTraversalDescriptor(tr); /* also store in the traversal descriptor that something has changed i.e., in the parallel case that the traversal descriptor list of nodes needs to be broadcast once again */ tr->td[0].traversalHasChanged = TRUE; #if (defined(_FINE_GRAIN_MPI) || defined(_USE_PTHREADS)) /* now here we enter the fork-join region for Pthreads */ /* start the parallel region and tell all threads to compute the log likelihood for their fraction of the data. This call is implemented in the case switch of execFunction in axml.c */ masterBarrier(THREAD_EVALUATE, tr); /* and now here we explicitly do the reduction operation , that is add over the per-thread and per-partition log likelihoods to obtain the overall log like over all sites and partitions */ /* for unpartitioned data that's easy, we just sum over the log likes computed by each thread, thread 0 stores his results in reductionBuffer[0] thread 1 in reductionBuffer[1] and so on */ /* This reduction for the partitioned case is more complicated because each thread needs to store the partial log like of each partition and we then need to collect and add everything */ #else /* and here is just the sequential case, we directly call evaluateIterative() above without having to tell the threads/processes that they need to compute this function now */ evaluateIterative(tr); #endif for(model = 0; model < tr->NumberOfModels; model++) result += tr->perPartitionLH[model]; /* set the tree data structure likelihood value to the total likelihood */ tr->likelihood = result; if(tr->useRecom) { unpinNode(tr->rvec, p->number, tr->mxtips); unpinNode(tr->rvec, q->number, tr->mxtips); } /* do some bookkeeping to have traversalHasChanged in a consistent state */ tr->td[0].traversalHasChanged = FALSE; }