Esempio n. 1
0
mama_status
qpidBridge_close (mamaBridge bridgeImpl)
{
    mama_status      status      = MAMA_STATUS_OK;
    mamaBridgeImpl*  bridge      = (mamaBridgeImpl*) bridgeImpl;
    wthread_t        timerThread;


    /* Remove the timer heap */
    if (NULL != gQpidTimerHeap)
    {
        /* The timer heap allows us to access it's thread ID for joining */
        timerThread = timerHeapGetTid (gQpidTimerHeap);
        if (0 != destroyHeap (gQpidTimerHeap))
        {
            mama_log (MAMA_LOG_LEVEL_ERROR,
                      "qpidBridge_close(): Failed to destroy QPID timer heap.");
            status = MAMA_STATUS_PLATFORM;
        }
        /* The timer thread expects us to be responsible for terminating it */
        wthread_join    (timerThread, NULL);
    }
    gQpidTimerHeap = NULL;

    /* Destroy once queue has been emptied */
    mamaQueue_destroyTimedWait (bridge->mDefaultEventQueue,
                                QPID_SHUTDOWN_TIMEOUT);

    /* Stop and destroy the io thread */
    qpidBridgeMamaIoImpl_stop ();

    return status;
}
/*  Description: Creates a timerHeap, starts dispatching  then creates   
 *               100 timers which destroys themselves by callback. Heap is
 *               then destroyed.
 *  
 *  Expected Result: Functions return zero
 */
TEST_F (CommonTimerTestC, createDestroyManyTimers)
{
    struct timeval  timeout;
    timerElement    timer[100]  = {NULL};
    timerHeap       heap        = NULL;
   
    timeout.tv_sec = 0;
    timeout.tv_usec = 500;
    
    ASSERT_EQ (0, createTimerHeap(&heap));

    ASSERT_EQ (0, startDispatchTimerHeap(heap));
    
    for(int i=0; i<100 ;i++)
    {
        ASSERT_EQ (0, createTimer(&timer[i], 
                                  heap, 
                                  onTimerFire, 
                                  &timeout, 
                                  heap));
    }
    sleep(2);
    
    ASSERT_EQ (0, destroyHeap(heap));
}
/*  Description: Creates a timerHeap, starts dispatching then destroys the
 *               heap 
 *  
 *  Expected Result: Functions return zero
 */
TEST_F (CommonTimerTestC, createDestroyHeap)
{
    timerHeap heap = NULL;

    ASSERT_EQ (0, createTimerHeap(&heap));
    
    ASSERT_EQ (0, startDispatchTimerHeap(heap));
    
    ASSERT_EQ (0, destroyHeap(heap));
}
Esempio n. 4
0
int main() {
  Heap *loadH = NULL;
  loadH = initHeap(loadH, loadComp, freeLoad);

  int i;
  for (i=0; i < 10; ++i) {
    registerLoad(loadH, NULL);
  }

  produce(30, loadConsume);
  destroyHeap(loadH);
  return 0;
}
/*  Description: Creates 10 timerHeaps, starts dispatching  on them all 
 *               then destroys them all.
 *  
 *  Expected Result: Functions return zero
 */
TEST_F (CommonTimerTestC, createDestroyManyHeaps)
{
    timerHeap heap = NULL;

    for(int i=0; i<10 ;i++)
    {
        ASSERT_EQ (0, createTimerHeap(&heap));

        ASSERT_EQ (0, startDispatchTimerHeap(heap));

        ASSERT_EQ (0, destroyHeap(heap));
    }
}
Esempio n. 6
0
// An implementation of brute k-NN search that uses a heap.
void bruteKHeap(matrix X, matrix Q, unint **NNs, float **dToNNs, unint K) {
    float temp[CL];
    int i, j, k,t;

    int nt = omp_get_max_threads();
    heap **hp;
    hp = (heap**)calloc(nt, sizeof(*hp));
    for(i=0; i<nt; i++) {
        hp[i] = (heap*)calloc(CL, sizeof(**hp));
        for(j=0; j<CL; j++)
            createHeap(&hp[i][j],K);
    }

    #pragma omp parallel for private(t,k,j,temp)
    for( i=0; i<Q.pr/CL; i++ ) {
        t = i*CL;
        unint tn = omp_get_thread_num();
        heapEl newEl;

        for(j=0; j<X.r; j++ ) {
            for(k=0; k<CL; k++) {
                //temp[k] = distVec( Q, X, t+k, j );
                temp[k] = distVecLB( Q, X, t+k, j, hp[tn][k].h[0].val );
            }
            for(k=0; k<CL; k++) {
                if( temp[k] <= hp[tn][k].h[0].val ) {
                    newEl.id=j;
                    newEl.val=temp[k];
                    replaceMax( &hp[tn][k], newEl);
                }
            }
        }
        for(j=0; j<CL; j++)
            if(t+j<Q.r)
                heapSort(&hp[tn][j], NNs[t+j], dToNNs[t+j]);

        for(j=0; j<CL; j++)
            reInitHeap(&hp[tn][j]);
    }

    for(i=0; i<nt; i++) {
        for(j=0; j<CL; j++)
            destroyHeap(&hp[i][j]);
        free(hp[i]);
    }
    free(hp);
}
/*  Description: Creates a timerHeap, starts dispatching  then creates a  
 *               timer which destroys itself in it's callback. Heap is
 *               then destroyed.
 *  
 *  Expected Result: Functions return zero
 */
TEST_F (CommonTimerTestC, createDestroyTimer)
{
    struct timeval  timeout;
    timerElement    timer   = NULL;
    timerHeap       heap    = NULL;

    timeout.tv_sec  = 0;
    timeout.tv_usec = 500;
    
    ASSERT_EQ (0, createTimerHeap(&heap));
    
    ASSERT_EQ (0, startDispatchTimerHeap(heap));
    
    ASSERT_EQ (0, createTimer(&timer, heap, onTimerFire, &timeout, heap));
    sleep(2);

    ASSERT_EQ (0, destroyHeap(heap));

}
Esempio n. 8
0
mama_status
zmqBridge_close (mamaBridge bridgeImpl)
{
    mama_status      status      = MAMA_STATUS_OK;
    mamaBridgeImpl*  bridge      = (mamaBridgeImpl*) bridgeImpl;
    wthread_t        timerThread;

    if (NULL ==  bridgeImpl)
    {
        return MAMA_STATUS_NULL_ARG;
    }

    /* Remove the timer heap */
    if (NULL != gOmzmqTimerHeap)
    {
        /* The timer heap allows us to access it's thread ID for joining */
        timerThread = timerHeapGetTid (gOmzmqTimerHeap);
        if (0 != destroyHeap (gOmzmqTimerHeap))
        {
            mama_log (MAMA_LOG_LEVEL_ERROR,
                      "zmqBridge_close(): Failed to destroy zmq timer heap.");
            status = MAMA_STATUS_PLATFORM;
        }
        /* The timer thread expects us to be responsible for terminating it */
        wthread_join    (timerThread, NULL);
    }
    gOmzmqTimerHeap = NULL;

    /* Destroy once queue has been emptied */
    mamaQueue_destroyTimedWait (bridge->mDefaultEventQueue,
                                ZMQ_SHUTDOWN_TIMEOUT);

    /* Stop and destroy the io thread */
    zmqBridgeMamaIoImpl_stop ();

    /* Wait for zmqBridge_start to finish before destroying implementation */
    if (NULL != bridgeImpl)
    {
        free (bridgeImpl);
    }

    return status;
}
Esempio n. 9
0
int main (int argc, char* argv[]) {
  int i; 
  pthread_t minions[MINIONS];

  /* Initialize Stuff */
  Knapsack* ks = initKnapsack(argv[1]);
  Heap* h = initHeap(DEFAULT_SIZE);
  ThreadArgs* ta = (ThreadArgs*)malloc(sizeof(ThreadArgs));
  ta->_ks = ks;
  ta->_h = h;

  /* Begin port of bb() */
  double rootUB = upperBound(ks, 0, ks->_capacity);
  Node* n = initNode(0, -1, rootUB, ks->_capacity, NULL);
  add(h, n);

  /* Create Minions */ 
  for ( i = 0; i < MINIONS; i++){
    pthread_create(&minions[i],NULL,minionDoWork,ta);
  }
  pthread_cond_signal(&ks->_cond);

  /* Return minions~ */
  for( i = 0; i < MINIONS; i++){
    pthread_join(minions[i],NULL);
  }

  /* Display Results */
  printf("Found solution: %d\n", ks->_lowerBound);
  printf("Best x=");
  for (i=0; i<ks->_nbItems-1; i++) {
    printf("%d,",ks->_bestX[i]);
  }
  printf("%d\n",ks->_bestX[ks->_nbItems-1]);
  printf("Nodes processed: %d\n", ks->_nodesProcessed);
  destroyKnapsack(ks);
  destroyHeap(h);
  free(ta);
  return 0;
}
Esempio n. 10
0
void setCover(Universe *Uni,int num_houses) {



	Heap *Q = createHeap();

	set_t *covered = create_set(num_houses);
	

	for(int i=0;i<Uni->size_of_universe;i++) {
		insert_in_heap(Q,i,Uni->sets[i].covered_items,max_func);
	}

	
 
	while(covered->covered_items < num_houses) {

		
		if(isEmpty(Q)) {
			break;
		}

		HeapItem max = removeTop(Q,max_func);
		

		
		//updating the covered set
		for(int i=0;i<Uni->sets[max.dataIndex].covered_items;i++) {

			//if its not covered 
			if(!covered->set[Uni->sets[max.dataIndex].set[i]]) {
					//set to the house being covered 
					covered->set[Uni->sets[max.dataIndex].set[i]] = 1;
					//increment number of covered houses
					covered->covered_items++;
			}
		}
	
		//flag the current set to be covered 
		Uni->sets[max.dataIndex].covered = 1;
				
 		//update the other sets
		for(int i=0;i<Uni->size_of_universe;i++) {

				//if they are not already covered
				if(!Uni->sets[i].covered) {

					//find set diff and update the heap
					int diff = set_diff(&Uni->sets[i],covered);
					changeKey(Q,i,diff,max_func);
				}
				
		}
		
	}

	if(covered->covered_items < num_houses) {
		fprintf(stderr, "Not enough houses to cover all houses.\n");
		exit(EXIT_FAILURE);
	}
	
	for(int i=0; i<Uni->size_of_universe;i++) {
		if(Uni->sets[i].covered) {
			printf("%d\n",i);
		}
	}


	destroyHeap(Q);
	free_set(covered);
	free_Universe(Uni);


}
Esempio n. 11
0
void produce(unsigned int n, void *(*func)(void *)) {
  int maxHandle = 8, readyId=-1, nC = 0;
  Heap *wHeap = NULL, *restHeap = NULL;
  wHeap = initHeap(wHeap, loadComp, freeLoad);
  restHeap = initHeap(restHeap, loadComp, freeLoad);
  unsigned int minThreshold = maxHandle > n ? n : maxHandle;
  pthread_t thList[minThreshold];
  pthread_attr_t attr;
  pthread_attr_init(&attr);
#ifdef __linux__
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
#endif

  for (readyId=0; readyId < minThreshold; ++readyId) {
    unsigned int *iNew = (unsigned int *)malloc(sizeof(unsigned int));
    *iNew = readyId;
    Load *l = createLoad(iNew);
    l->thId = readyId;
    addLoad(wHeap, l);
    pthread_create(thList + readyId, &attr, func, l);
  }

  int i, minFreeLoadCount = minThreshold >> 1;
  if (readyId < n) {
    heapifyFromHead(wHeap);
    i = readyId;
    int chillThId = -1;
    Load *wHead = NULL;
    while (i < n) {
      printf("\033[32mwHeap: "); printHeap(wHeap, printLoad);
      printf("\n\033[33mrHeap: "); printHeap(restHeap, printLoad);
      printf("\ni:%d n:%d chillThId: %d\033[00m\n", i, n, chillThId);

      if ((wHead = peek(wHeap)) != NULL) {
        printf("wHead: %d\n", wHead->id);

        void *data = NULL;
        int join = pthread_join(thList[wHead->thId], &data);
        printf("newJoin: %d\n", join);
        if (! join) {
          printf("joined: %d\n", wHead->thId);
          if (data != NULL) {
            printf("\033[36m\nRetr %s :%d\033[00m\n", (char *)data, wHead->thId); 
            free(data);
          }
          chillThId = wHead->thId;
          printf("chillThId: %d\n", chillThId);
        #ifdef DEBUG
          printf("wHead->thId: %d\n", wHead->thId);
        #endif
          heapExtract(wHeap, (const void **)&wHead); 
          wHead->id = getAvailableId(restHeap);
          addLoad(restHeap, wHead); 
          printf("rHeap"); printHeap(restHeap, printLoad);
          wHead = NULL;
        }
      }

      if (getSize(wHeap) < minFreeLoadCount && peek(restHeap) != NULL) {
      #ifdef DEBUG
        printf("Peeked: %p\n", peek(restHeap));
        printf("\nrestHeap\n");
      #endif
        heapExtract(restHeap, (const void **)&wHead);
        if (wHead == NULL) continue;
      #ifdef DEBUG
        printf("wHead->thId:: %p\n", wHead);
      #endif
        wHead->thId = chillThId;
        *((int *)wHead->data) = i;

        addLoad(wHeap, wHead);
        int createStatus =\
          pthread_create(thList + wHead->thId, &attr, func, wHead);
        printf("createdStatus: %d i: %d\n", createStatus, i);
        if (! createStatus) {
          ++i;
        }
      }
    }
  }

  while (! isEmpty(wHeap)) {
    Load *tmpHead = NULL;
    if (! heapExtract(wHeap, (const void **)&tmpHead) && tmpHead != NULL) {
      void *data = NULL;
      if (! pthread_join(thList[tmpHead->thId], &data)) {
        if (data != NULL) {
          printf("i: %d Joined msg: %s\n", i, (char *)data);
          free(data);
        }
      }
    }
    freeLoad(tmpHead);
  }

  destroyHeap(wHeap);
  destroyHeap(restHeap);
}
Esempio n. 12
0
// This method is the same as the above bruteList method, but for k-nn search.
// It uses a heap.
void bruteListK(matrix X, matrix Q, rep *ri, intList *toSearch, unint numReps, unint **NNs, float **dToNNs, unint K) {
    float temp;
    unint i, j, k, l;

    unint nt = omp_get_max_threads();
    unint m = Q.r;

    heap **hp;
    hp = (heap**)calloc(nt, sizeof(*hp));
    for(i=0; i<nt; i++) {
        hp[i] = (heap*)calloc(m, sizeof(**hp));
        for(j=0; j<m; j++)
            createHeap(&hp[i][j],K);
    }

    #pragma omp parallel for private(j,k,l,temp)
    for( i=0; i<numReps; i++ ) {
        unint tn = omp_get_thread_num();
        heapEl newEl;

        for( j=0; j< toSearch[i].len/CL; j++) { //toSearch is assumed to be padded
            unint row = j*CL;
            unint qInd[CL];
            for(k=0; k<CL; k++)
                qInd[k] = toSearch[i].x[row+k];
            rep rt = ri[i];
            for(k=0; k<rt.len; k++) {
                for(l=0; l<CL; l++ ) {
                    if(qInd[l]!=DUMMY_IDX) {
                        temp = distVecLB( Q, X, qInd[l], rt.lr[k], hp[tn][qInd[l]].h[0].val );
                        if( temp < hp[tn][qInd[l]].h[0].val ) {
                            newEl.id = rt.lr[k];
                            newEl.val = temp;
                            replaceMax( &hp[tn][qInd[l]], newEl );
                        }
                    }
                }
            }
        }
    }

    // Now merge the NNs found by each thread.  Currently this performs the
    // merge within one thread, but should eventually be done in a proper
    // parallel-reduce fashion.
    unint **tInds;
    float **tVals;
    tInds = (unint**)calloc(nt, sizeof(*tInds));
    tVals = (float**)calloc(nt, sizeof(*tVals));
    for( i=0; i<nt; i++ ) {
        tInds[i] = (unint*)calloc(K, sizeof(**tInds) );
        tVals[i] = (float*)calloc(K, sizeof(**tVals) );
    }

    size_t *indVec = (size_t*)calloc(nt*K, sizeof(*indVec));
    size_t *tempInds = (size_t*)calloc(nt*K, sizeof(*tempInds));
    float *valVec = (float*)calloc(nt*K, sizeof(*valVec));

    for( i=0; i<m; i++) {

        for( j=0; j<nt; j++) {
            heapSort( &hp[j][i], tInds[j], tVals[j] );
            for( k=0; k<K; k++) {
                indVec[j*K + k] = tInds[j][k];
                valVec[j*K + k] = tVals[j][k];
            }
        }

        gsl_sort_float_index(tempInds, valVec, 1, nt*K);
        for( j=0; j<K; j++ ) {
            dToNNs[i][j] = valVec[tempInds[j]];
            NNs[i][j] = indVec[tempInds[j]];
        }
    }

    free(tempInds);
    free(indVec);
    free(valVec);
    for( i=0; i<nt; i++ ) {
        free(tInds[i]);
        free(tVals[i]);
    }
    free(tInds);
    free(tVals);
    for(i=0; i<nt; i++) {
        for(j=0; j<m; j++)
            destroyHeap(&hp[i][j]);
        free(hp[i]);
    }
    free(hp);
}
Esempio n. 13
0
int main (int argc, char* argv[]) {
  /* Read from file input */
  FILE *fp;
  Item* temp;
  Knapsack* ks = (Knapsack*)malloc(sizeof(Knapsack));
  char* fName = argv[1];
  fp = fopen(fName,"r");
  fscanf(fp,"%d", &ks->_nbItems);

  // We randomly chose nbItems/4 as an initial heap size.
  // It's something to tweak as we go on
  Heap* h = initHeap(ks->_nbItems/4);
  ks->_items = (Item**)malloc(sizeof(Item*)*ks->_nbItems);
  ks->_lowerBound = 0;

  // Each row of input has an unused counter variable at the beginning.
  // We'll use fscanf to dump it into j. 
  int i, j;
  /* For each of the items, read in their values and create the node */
  for (i = 0; i < ks->_nbItems; i++) {
    ks->_items[i] = (Item*)malloc(sizeof(Item));
    fscanf(fp,"%d %d %d", &j, &ks->_items[i]->_value, &ks->_items[i]->_weight);
  }
  ks->_bestX = (char*)calloc(ks->_nbItems, sizeof(char));
  fscanf(fp,"%d",&ks->_capacity);

  fclose(fp);
  /* Sort 'em */
  qsort(ks->_items, ks->_nbItems, sizeof(Item*), compare); 

  /* Begin port of bb() */
  
  double rootUB = upperBound(ks, 0, ks->_capacity);
  // I don't understand why depth is -1 here but I'll go with it
  Node* n = initNode(0, -1, rootUB, ks->_capacity, NULL);
  add(h, n);

  /* Begin port of run() */
  int nodesProcessed = 0;
  while (!isEmpty(h)) {
    n = removeMax(h);
    if (n->_depth >= (ks->_nbItems-1)) {
      if (n->_value > ks->_lowerBound) {
        printf("tighten LB to %d\n", n->_value);
        ks->_lowerBound = n->_value;
        for (i=0; i < n->_depth+1; i++) {
          ks->_bestX[i] = n->_x[i];
        }
        for (i=n->_depth+1; i<ks->_nbItems; i++) {
          ks->_bestX[i] = 0;
        }
        destroyNode(n);
      }
    } else {
      processNode(ks, h, n);
      nodesProcessed++;
    }
  }
  printf("Found solution: %d\n", ks->_lowerBound);
  printf("Best x=");
  for (i=0; i<ks->_nbItems-1; i++) {
    printf("%d,",ks->_bestX[i]);
  }
  printf("%d\n",ks->_bestX[ks->_nbItems-1]);
  printf("Nodes processed: %d\n", nodesProcessed);
  // Fix those pesky memory leaks.
  destroyKnapsack(ks);
  destroyHeap(h);
  return 0;
}
Esempio n. 14
0
//Exact k-NN search with the RBC
void searchExactK(matrix q, matrix x, matrix r, rep *ri, unint **NNs, real **dNNs, unint K){
  unint i, j, k;
  unint *repID = (unint*)calloc(q.pr, sizeof(*repID));
  real **dToReps = (real**)calloc(q.pr, sizeof(*dToReps));
  for(i=0; i<q.pr; i++)
    dToReps[i] = (real*)calloc(K, sizeof(**dToReps));
  intList *toSearch = (intList*)calloc(r.pr, sizeof(*toSearch));
  for(i=0;i<r.pr;i++)
    createList(&toSearch[i]);
  int nt = omp_get_max_threads();

  float ***d;  //d is indexed by: thread, cache line #, rep #
  d = (float***)calloc(nt, sizeof(*d));
  for(i=0; i<nt; i++){
    d[i] = (float**)calloc(CL, sizeof(**d));
    for(j=0; j<CL; j++){
      d[i][j] = (float*)calloc(r.pr, sizeof(***d));
    }
  }
  
  heap **hp;
  hp = (heap**)calloc(nt, sizeof(*hp));
  for(i=0; i<nt; i++){
    hp[i] = (heap*)calloc(CL, sizeof(**hp));
    for(j=0; j<CL; j++)
      createHeap(&hp[i][j],K);
  }
  
#pragma omp parallel for private(j,k)
  for(i=0; i<q.pr/CL; i++){
    unint row = i*CL;
    unint tn = omp_get_thread_num();
    heapEl newEl; 

    for( j=0; j<r.r; j++ ){
      for(k=0; k<CL; k++){
	d[tn][k][j] = distVec(q, r, row+k, j);
	if( d[tn][k][j] < hp[tn][k].h[0].val ){
	  newEl.id = j;
	  newEl.val = d[tn][k][j];
	  replaceMax( &hp[tn][k], newEl );
	}
      }
    }
    for(j=0; j<r.r; j++ ){
      for(k=0; k<CL; k++ ){
	real minDist = hp[tn][k].h[0].val;
	real temp = d[tn][k][j];
	if( row + k<q.r && minDist >= temp - ri[j].radius && 3.0*minDist >= temp ){
#pragma omp critical
	  {
	    addToList(&toSearch[j], row+k);
	  }
	}
      }
    }
    for(j=0; j<CL; j++)
      reInitHeap(&hp[tn][j]);
  }

  for(i=0; i<r.r; i++){
    while(toSearch[i].len % CL != 0)
      addToList(&toSearch[i],DUMMY_IDX);
  }

  bruteListK(x,q,ri,toSearch,r.r,NNs,dNNs,K);

  
  //clean-up
  for(i=0; i<nt; i++){
    for(j=0; j<CL; j++)
      destroyHeap(&hp[i][j]);
    free(hp[i]);
  }
  free(hp);
  for(i=0;i<r.pr;i++)
    destroyList(&toSearch[i]);
  free(toSearch);
  free(repID);
  for(i=0;i<q.pr; i++)
    free(dToReps[i]);
  free(dToReps);
  for(i=0; i<nt; i++){
    for(j=0; j<CL; j++)
      free(d[i][j]); 
    free(d[i]);
  }
  free(d);
}
	void finalizeResources(){
		if( isInfoEnabled()) info( "Liberando recursos" );
		destroyHeap(getGlobalHeap());
		finalizeWinsock();
	}
Esempio n. 16
0
Heap<T>::~Heap() {
    destroyHeap();
}
Esempio n. 17
0
// Performs a brute force K-NN search, but only between queries and points
// belonging to each query's nearest representative.  This method is used by
// the one-shot algorithm.
void bruteMapK(matrix X, matrix Q, rep *ri, unint* qMap, unint **NNs, float **dToNNs, unint K) {
    unint i, j, k;

    //Sort the queries, so that queries matched to a particular representative
    //will be processed together, improving cache performance.
    size_t *qSort = (size_t*)calloc(Q.pr, sizeof(*qSort));
    gsl_sort_uint_index(qSort,qMap,1,Q.r);

    unint nt = omp_get_max_threads();

    heap **hp;
    hp = (heap**)calloc(nt, sizeof(*hp));
    for(i=0; i<nt; i++) {
        hp[i] = (heap*)calloc(CL, sizeof(**hp));
        for(j=0; j<CL; j++)
            createHeap(&hp[i][j],K);
    }


    #pragma omp parallel for private(j,k) schedule(static)
    for( i=0; i<Q.pr/CL; i++ ) {
        unint row = i*CL;
        unint tn = omp_get_thread_num();
        heapEl newEl;

        float temp[CL];
        rep rt[CL];
        unint maxLen = 0;
        for(j=0; j<CL; j++) {
            rt[j] = ri[qMap[qSort[row+j]]];
            maxLen = MAX(maxLen, rt[j].len);
            temp[j]=0.0; //gets rid of compiler warning
        }

        for(j=0; j<maxLen; j++ ) {
            for(k=0; k<CL; k++ ) {
                if( j<rt[k].len )
                    temp[k] = distVecLB( Q, X, qSort[row+k], rt[k].lr[j], hp[tn][k].h[0].val  );
            }

            for(k=0; k<CL; k++ ) {
                if( j<rt[k].len ) {
                    if( temp[k] < hp[tn][k].h[0].val ) {
                        newEl.id = rt[k].lr[j];
                        newEl.val = temp[k];
                        replaceMax( &hp[tn][k], newEl );
                    }
                }
            }
        }

        for(j=0; j<CL; j++)
            heapSort( &hp[tn][j], NNs[qSort[row+j]], dToNNs[qSort[row+j]] );

        for(j=0; j<CL; j++)
            reInitHeap(&hp[tn][j]);
    }

    for(i=0; i<nt; i++) {
        for(j=0; j<CL; j++)
            destroyHeap(&hp[i][j]);
        free(hp[i]);
    }
    free(hp);
    free(qSort);
}