Пример #1
0
/*
    Returns the value with the lowest priority and removes it
    from the queue.
    This is the same as pq_find followed by pq_delete.
    returns: 1 if successful, 0 if failed (pq is empty)
    val and priority are returned in the pointers
*/
int pq_dequeue(struct priority_queue *pq, int *val, int *priority)
{
    if (pq == NULL) return 0;

    *val = pq->heap[1].val;
    *priority = pq->heap[1].priority;

    return pq_delete(pq);
}
key_type pq_delete_min( implicit_heap *queue )
{
    return pq_delete( queue, queue->nodes[0] );
}
int main( int argc, char** argv )
{
    uint64_t i;

    // pointers for casting
    pq_op_create *op_create;
    pq_op_destroy *op_destroy;
    pq_op_clear *op_clear;
    pq_op_get_key *op_get_key;
    pq_op_get_item *op_get_item;
    pq_op_get_size *op_get_size;
    pq_op_insert *op_insert;
    pq_op_find_min *op_find_min;
    pq_op_delete *op_delete;
    pq_op_delete_min *op_delete_min;
    pq_op_decrease_key *op_decrease_key;
    //pq_op_meld *op_meld;
    pq_op_empty *op_empty;

    // temp dummies for readability
    pq_type *q;//, *r;
    pq_node_type *n;

    if( argc < 2 )
        exit( -1 );

    int trace_file = open( argv[1], O_RDONLY );
    if( trace_file < 0 )
    {
        fprintf( stderr, "Could not open file.\n" );
        return -1;
    }

    pq_trace_header header;
    pq_trace_read_header( trace_file, &header );
    close( trace_file );

    //printf("Header: (%llu,%lu,%lu)\n",header.op_count,header.pq_ids,
    //    header.node_ids);

    pq_op_blank *ops = calloc( MIN( header.op_count, CHUNK_SIZE ),
        sizeof( pq_op_blank ) );
    pq_type **pq_index = calloc( header.pq_ids, sizeof( pq_type* ) );
    pq_node_type **node_index = calloc( header.node_ids,
        sizeof( pq_node_type* ) );
    if( ops == NULL || pq_index == NULL || node_index == NULL )
    {
        fprintf( stderr, "Calloc fail.\n" );
        return -1;
    }

#ifdef USE_QUAKE
    mem_capacities[0] = header.node_ids << 2;
#else
    mem_capacities[0] = header.node_ids;
#endif

#ifdef USE_EAGER
    mem_map *map = mm_create( mem_types, mem_sizes, mem_capacities );
#else
    mem_map *map = mm_create( mem_types, mem_sizes );
#endif

    uint64_t op_remaining, op_chunk;
    int status;
    struct timeval t0, t1;
    uint32_t iterations = 0;
    uint32_t total_time = 0;
    key_type k;
    //pq_node_type *min;

#ifndef CACHEGRIND
    while( iterations < 5 || total_time < PQ_MIN_USEC )
    {
        mm_clear( map );
        iterations++;
#endif

        trace_file = open( argv[1], O_RDONLY );
        if( trace_file < 0 )
        {
            fprintf( stderr, "Could not open file.\n" );
            return -1;
        }
        pq_trace_read_header( trace_file, &header );
        op_remaining = header.op_count;

        while( op_remaining > 0 )
        {
            op_chunk = MIN( CHUNK_SIZE, op_remaining );
            op_remaining -= op_chunk;

            for( i = 0; i < op_chunk; i++ )
            {
                status = pq_trace_read_op( trace_file, ops + i );
                if( status == -1 )
                {
                    fprintf( stderr, "Invalid operation!" );
                    return -1;
                }
            }

#ifndef CACHEGRIND
            gettimeofday(&t0, NULL);
#endif

            for( i = 0; i < op_chunk; i++ )
            {
                switch( ops[i].code )
                {
                    case PQ_OP_CREATE:
                        op_create = (pq_op_create*) ( ops + i );
                        //printf("pq_create(%d)\n", op_create->pq_id);
                        pq_index[op_create->pq_id] = pq_create( map );
                        break;
                    case PQ_OP_DESTROY:
                        op_destroy = (pq_op_destroy*) ( ops + i );
                        //printf("pq_destroy(%d)\n", op_destroy->pq_id);
                        q = pq_index[op_destroy->pq_id];
                        pq_destroy( q );
                        pq_index[op_destroy->pq_id] = NULL;
                        break;
                    case PQ_OP_CLEAR:
                        op_clear = (pq_op_clear*) ( ops + i );
                        //printf("pq_clear(%d)\n", op_clear->pq_id );
                        q = pq_index[op_clear->pq_id];
                        pq_clear( q );
                        break;
                    case PQ_OP_GET_KEY:
                        op_get_key = (pq_op_get_key*) ( ops + i );
                        //printf("pq_get_key(%d,%d)\n", op_get_key->pq_id,
                        //    op_get_key->node_id );
                        q = pq_index[op_get_key->pq_id];
                        n = node_index[op_get_key->node_id];
                        pq_get_key( q, n );
                        break;
                    case PQ_OP_GET_ITEM:
                        op_get_item = (pq_op_get_item*) ( ops + i );
                        //printf("pq_get_item(%d,%d)\n", op_get_item->pq_id,
                        //    op_get_item->node_id);
                        q = pq_index[op_get_item->pq_id];
                        n = node_index[op_get_item->node_id];
                        pq_get_item( q, n );
                        break;
                    case PQ_OP_GET_SIZE:
                        op_get_size = (pq_op_get_size*) ( ops + i );
                        //printf("pq_get_size(%d)\n", op_get_size->pq_id);
                        q = pq_index[op_get_size->pq_id];
                        pq_get_size( q );
                        break;
                    case PQ_OP_INSERT:
                        op_insert = (pq_op_insert*) ( ops + i );
                        //printf("pq_insert(%d,%d,%llu,%d)\n", op_insert->pq_id,
                        //    op_insert->node_id, op_insert->key, op_insert->item );
                        q = pq_index[op_insert->pq_id];
                        node_index[op_insert->node_id] = pq_insert( q,
                            op_insert->item, op_insert->key );
                        break;
                    case PQ_OP_FIND_MIN:
                        op_find_min = (pq_op_find_min*) ( ops + i );
                        //printf("pq_find_min(%d)\n", op_find_min->pq_id );
                        q = pq_index[op_find_min->pq_id];
                        pq_find_min( q );
                        break;
                    case PQ_OP_DELETE:
                        op_delete = (pq_op_delete*) ( ops + i );
                        //printf("pq_delete(%d,%d)\n", op_delete->pq_id,
                        //    op_delete->node_id );
                        q = pq_index[op_delete->pq_id];
                        n = node_index[op_delete->node_id];
                        pq_delete( q, n );
                        break;
                    case PQ_OP_DELETE_MIN:
                        op_delete_min = (pq_op_delete_min*) ( ops + i );
                        //printf("pq_delete_min(%d)\n", op_delete_min->pq_id);
                        q = pq_index[op_delete_min->pq_id];
                        //min = pq_find_min( q );
                        k = pq_delete_min( q );
#ifdef CACHEGRIND
                        if( argc > 2 )
                            printf("%llu\n",k);
#endif
                        break;
                    case PQ_OP_DECREASE_KEY:
                        op_decrease_key = (pq_op_decrease_key*) ( ops + i );
                        //printf("pq_decrease_key(%d,%d,%llu)\n", op_decrease_key->pq_id,
                        //    op_decrease_key->node_id, op_decrease_key->key);
                        q = pq_index[op_decrease_key->pq_id];
                        n = node_index[op_decrease_key->node_id];
                        pq_decrease_key( q, n, op_decrease_key->key );
                        break;
                    /*case PQ_OP_MELD:
                        printf("Meld.\n");
                        op_meld = (pq_op_meld*) ( ops + i );
                        q = pq_index[op_meld->pq_src1_id];
                        r = pq_index[op_meld->pq_src2_id];
                        pq_index[op_meld->pq_dst_id] = pq_meld( q, r );
                        break;*/
                    case PQ_OP_EMPTY:
                        op_empty = (pq_op_empty*) ( ops + i );
                        //printf("pq_empty(%d)\n", op_empty->pq_id);
                        q = pq_index[op_empty->pq_id];
                        pq_empty( q );
                        break;
                    default:
                        break;
                }
                //verify_queue( pq_index[0], header.node_ids );
            }

#ifndef CACHEGRIND
            gettimeofday(&t1, NULL);
            total_time += (t1.tv_sec - t0.tv_sec) * 1000000 +
                (t1.tv_usec - t0.tv_usec);
#endif
        }

        close( trace_file );
#ifndef CACHEGRIND
    }
#endif

    for( i = 0; i < header.pq_ids; i++ )
    {
        if( pq_index[i] != NULL )
            pq_destroy( pq_index[i] );
    }

    mm_destroy( map );
    free( pq_index );
    free( node_index );
    free( ops );

#ifndef CACHEGRIND
    printf( "%d\n", total_time / iterations );
#endif

    return 0;
}
Пример #4
0
/**
 * Repeatedly merge the closest pair of the given markers until they don't overlap.
 *
 * The centroid rule is used for merging.  I.e. each marker's area represents
 * a population of points. Merging two markers removes the originals and creates a
 * new marker with area the sum of the originals and center at the average position
 * of the two merged populations.
 *
 * The markers array must include extra buffer space.  If there are n markers, the
 * array must have 2n-1 spaces, with only the first n initialized.
 *
 * The number of markers after merging is returned. Zero or more of these will be
 * marked deleted_p and should be ignored.
 *
 * This algorithm is O(n k log n), where k is the maximum number of simultaneously
 * overlapping markers in the original, unmerged set.
 */
int merge_markers_fast(MARKER_INFO *info, MARKER *markers, int n_markers) {
    int augmented_length = 2 * n_markers - 1;
    NewArrayDecl(int, n_nghbr, augmented_length);
    NewArrayDecl(MARKER_DISTANCE, mindist, augmented_length);
    NewArrayDecl(int, inv_nghbr_head, augmented_length);
    NewArrayDecl(int, inv_nghbr_next, augmented_length);
    NewArrayDecl(int, tmp, augmented_length); // Too big
    // Do not free the following array!  It's owned by the priority queue.
    NewArrayDecl(int, heap, augmented_length); // Too big

    // Specialized quadtree supports finding closest marker to any given one.
    QUADTREE_DECL(qt);

    // Priority queue keyed on distances of overlapping pairs of markers.
    PRIORITY_QUEUE_DECL(pq);

    /// Extent of markers in the domain.
    MARKER_EXTENT ext[1];

    // Get a bounding box for the whole collection of markers.
    get_marker_array_extent(markers, n_markers, ext);

    // Set up the quadtree with the bounding box. Choose tree depth heuristically.
    int max_depth = high_bit_position(n_markers) / 4 + 3;
    qt_setup(qt, max_depth, ext->x, ext->y, ext->w, ext->h, info);

    // Insert all the markers in the quadtree.
    for (int i = 0; i < n_markers; i++)
        qt_insert(qt, markers + i);

    // Set all the inverse nearest neighbor links to null.
    for (int i = 0; i < augmented_length; i++)
        inv_nghbr_head[i] = inv_nghbr_next[i] = -1;

    // Initialize the heap by adding an index for each overlapping pair. The
    // The heap holds indices into the array of min-distance keys. An index for
    // pair a->bis added iff markers with indices a and b overlap and b < a.
    int heap_size = 0;
    for (int a = 0; a < n_markers; a++) {
        int b = qt_nearest_wrt(markers, qt, a);
        if (0 <= b && b < a) {
            n_nghbr[a] = b;
            mindist[a] = mr_distance(info, markers + a, markers + b);
            heap[heap_size++] = a;

            // Here we are building a linked list of markers that have b as nearest.
            inv_nghbr_next[a] = inv_nghbr_head[b];
            inv_nghbr_head[b] = a;
        }
    }

    // Now install the raw heap array into the priority queue. After this it's owned by the queue.
    pq_set_up_heap(pq, heap, heap_size, mindist, augmented_length); // Too big

    while (!pq_empty_p(pq)) {

        // Get nearest pair from priority queue.
        int a = pq_get_min(pq);
        int b = n_nghbr[a];

        // Delete both of the nearest pair from all data structures.
        pq_delete(pq, b);
        qt_delete(qt, markers + a);
        qt_delete(qt, markers + b);
        mr_set_deleted(markers + a);
        mr_set_deleted(markers + b);

        // Capture the inv lists of both a and b in tmp.
        int tmp_size = 0;
        for (int p = inv_nghbr_head[a]; p >= 0; p = inv_nghbr_next[p])
            if (!markers[p].deleted_p)
                tmp[tmp_size++] = p;
        for (int p = inv_nghbr_head[b]; p >= 0; p = inv_nghbr_next[p])
            if (!markers[p].deleted_p)
                tmp[tmp_size++] = p;

        // Create a new merged marker. Adding it after all others means
        // nothing already in the heap could have it as nearest.
        int aa = n_markers++;
        mr_merge(info, markers, aa, a, b);

        // Add to quadtree.
        qt_insert(qt, markers + aa);

        // Find nearest overlapping neighbor of the merged marker, if any.
        int bb = qt_nearest_wrt(markers, qt, aa);
        if (0 <= bb) {
            n_nghbr[aa] = bb;
            mindist[aa] = mr_distance(info, markers + aa, markers + bb);
            pq_add(pq, aa);
            inv_nghbr_next[aa] = inv_nghbr_head[bb];
            inv_nghbr_head[bb] = aa;
        }

        // Reset the nearest neighbors of the inverse neighbors of the deletions.
        for (int i = 0; i < tmp_size; i++) {
            int aa = tmp[i];
            int bb = qt_nearest_wrt(markers, qt, aa);
            if (0 <= bb && bb < aa) {
                n_nghbr[aa] = bb;
                mindist[aa] = mr_distance(info, markers + aa, markers + bb);
                pq_update(pq, aa);
                inv_nghbr_next[aa] = inv_nghbr_head[bb];
                inv_nghbr_head[bb] = aa;
            } else {
                pq_delete(pq, aa);
            }
        }
    }
    qt_clear(qt);
    pq_clear(pq);
    Free(n_nghbr);
    Free(mindist);
    Free(inv_nghbr_head);
    Free(inv_nghbr_next);
    Free(tmp);
    return n_markers;
}
Пример #5
0
// Return the top of the queue
int pq_dequeue(prio_q* pq)
{
    int n = pq_delete(pq, 0);
    return n;
}