Beispiel #1
0
void thorium_actor_send_range_default(struct thorium_actor *actor, struct core_vector *actors,
                int first, int last,
                struct thorium_message *message)
{
#ifdef USE_BINOMIAL_TREE
    struct core_vector destinations;
    struct core_memory_pool *ephemeral_memory;
    int name;

    ephemeral_memory = thorium_actor_get_ephemeral_memory(actor);
    core_vector_init(&destinations, sizeof(int));
    core_vector_set_memory_pool(&destinations, ephemeral_memory);
    core_vector_copy_range(actors, first, last, &destinations);

    /*
     * Set the source now.
     */
    name = thorium_actor_name(actor);
    thorium_message_set_source(message, name);

    thorium_actor_send_range_binomial_tree(actor, &destinations, message);

    core_vector_destroy(&destinations);
#else

    thorium_actor_send_range_loop(actor, actors, first, last, message);
#endif
}
Beispiel #2
0
static void source_init(struct thorium_actor *self)
{
    struct source *concrete_self;
    int argc;
    char **argv;

    concrete_self = thorium_actor_concrete_actor(self);

    concrete_self->message_count = 0;

    argc = thorium_actor_argc(self);
    argv = thorium_actor_argv(self);

    concrete_self->event_count = DEFAULT_EVENT_COUNT;

    if (core_command_has_argument(argc, argv, OPTION_EVENT_COUNT)) {
        concrete_self->event_count = core_command_get_argument_value_int(argc, argv, OPTION_EVENT_COUNT);
    }

    core_vector_init(&concrete_self->targets, sizeof(int));
    core_vector_set_memory_pool(&concrete_self->targets,
                    thorium_actor_get_persistent_memory_pool(self));

    concrete_self->target = -1;
}
Beispiel #3
0
void thorium_actor_send_range_default(struct thorium_actor *actor, struct core_vector *actors,
                int first, int last,
                struct thorium_message *message)
{
    int use_binomial_tree;
    struct core_vector destinations;
    struct core_memory_pool *ephemeral_memory;
    int name;
    int action;

    action = thorium_message_action(message);
    use_binomial_tree = 0;

#ifdef USE_BINOMIAL_TREE

    /*
     * ACTION_ASK_TO_STOP basically kills actors (if they agree to).
     * It is a bad idea to use a binomial tree to send this death signal
     * since intermediate actors can die before acting as relays.
     */
    if (action != ACTION_ASK_TO_STOP)
        use_binomial_tree = 1;
#endif

    if (!use_binomial_tree) {
        thorium_actor_send_range_loop(actor, actors, first, last, message);
        return;
    }

    tracepoint(thorium_binomial_tree, send_range, message, (int)core_vector_size(actors));

    /*
     * Otherwise, use the binomial tree code path. This algorithm is better since it distributed
     * the sending operations intot a binomial tree where there are a lot of intermediate
     * actors (to be exact, the number of intermediate actors is close to log2(actors.size)).
     */
    ephemeral_memory = thorium_actor_get_ephemeral_memory(actor);
    core_vector_init(&destinations, sizeof(int));
    core_vector_set_memory_pool(&destinations, ephemeral_memory);

    CORE_DEBUGGER_ASSERT(core_vector_empty(&destinations));

    core_vector_copy_range(actors, first, last, &destinations);

    /*
     * Set the source now.
     */
    name = thorium_actor_name(actor);
    thorium_message_set_source(message, name);

    thorium_actor_send_range_binomial_tree(actor, &destinations, message);

    core_vector_destroy(&destinations);
}
Beispiel #4
0
void core_vector_init(struct core_vector *self, int element_size)
{
    self->element_size = element_size;
    self->maximum_size = 0;
    self->size = 0;
    self->data = NULL;

    core_vector_set_memory_pool(self, NULL);

    self->profile_allocate_calls = 0;
    self->profile_free_calls = 0;
}
Beispiel #5
0
void core_vector_destroy(struct core_vector *self)
{
    if (self->data != NULL) {
        core_memory_pool_free(self->memory, self->data);
        ++self->profile_free_calls;
        self->data = NULL;
    }

    CORE_DEBUGGER_ASSERT(self->profile_allocate_calls == self->profile_free_calls);

    self->element_size = 0;
    self->maximum_size = 0;
    self->size = 0;

    core_vector_set_memory_pool(self, NULL);
}
Beispiel #6
0
void biosal_input_stream_count_reply_mock(struct thorium_actor *self, struct thorium_message *message)
{
    struct biosal_input_stream *concrete_self;
    void *buffer;
    int count;
    struct core_vector mega_blocks;
    char *file;
    struct core_memory_pool *ephemeral_memory;
    uint64_t result;
    struct biosal_mega_block *block;

    concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(self);
    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);

    core_vector_init(&mega_blocks, 0);
    core_vector_set_memory_pool(&mega_blocks, ephemeral_memory);
    core_vector_unpack(&mega_blocks, buffer);

    block = core_vector_at_last(&mega_blocks);

    result = biosal_mega_block_get_entries(block);

#if 0
    file = core_string_get(&concrete_self->file_for_parallel_counting);
#endif

    file = concrete_self->file_name;

    printf("%s/%d COUNT_IN_PARALLEL result for %s is %" PRIu64 "\n",
                    thorium_actor_script_name(self),
                    thorium_actor_name(self),
                    file,
                    result);

    core_vector_destroy(&mega_blocks);

    thorium_actor_send_buffer(self, concrete_self->controller,
                    ACTION_INPUT_COUNT_IN_PARALLEL_REPLY, count, buffer);
}
Beispiel #7
0
void biosal_assembly_arc_classifier_push_arc_block(struct thorium_actor *self, struct thorium_message *message)
{
    struct biosal_assembly_arc_classifier *concrete_self;
    int source;
    struct biosal_assembly_arc_block input_block;
    struct biosal_assembly_arc_block *output_block;
    struct core_vector output_blocks;
    struct core_memory_pool *ephemeral_memory;
    int consumer_count;
    struct core_vector *input_arcs;
    struct core_vector *output_arcs;
    int size;
    int i;
    struct biosal_assembly_arc *arc;
    void *buffer;
    int count;
    struct biosal_dna_kmer *kmer;
    int consumer_index;
    int arc_count;
    int consumer;
    struct thorium_message new_message;
    int new_count;
    void *new_buffer;
    int *bucket;
    int maximum_pending_requests;
    int maximum_buffer_length;
    int reservation;

    count = thorium_message_count(message);
    buffer = thorium_message_buffer(message);

    if (count == 0) {
        printf("Error, count is 0 (classifier_push_arc_block)\n");
        return;
    }

    concrete_self = (struct biosal_assembly_arc_classifier *)thorium_actor_concrete_actor(self);
    source = thorium_message_source(message);
    consumer_count = core_vector_size(&concrete_self->consumers);
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);

    CORE_DEBUGGER_LEAK_DETECTION_BEGIN(ephemeral_memory, classify_arcs);

    core_vector_init(&output_blocks, sizeof(struct biosal_assembly_arc_block));
    core_vector_set_memory_pool(&output_blocks, ephemeral_memory);

    biosal_assembly_arc_block_init(&input_block, ephemeral_memory, concrete_self->kmer_length,
                    &concrete_self->codec);

#ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG
    printf("UNPACKING\n");
#endif

    biosal_assembly_arc_block_unpack(&input_block, buffer, concrete_self->kmer_length,
                    &concrete_self->codec, ephemeral_memory);

#ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG
    printf("OK\n");
#endif

    input_arcs = biosal_assembly_arc_block_get_arcs(&input_block);

    /*
     * Configure the ephemeral memory reservation.
     */
    arc_count = core_vector_size(input_arcs);
    reservation = (arc_count / consumer_count) * 2;

    core_vector_resize(&output_blocks, consumer_count);

    CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

    /*
     * Initialize output blocks.
     * There is one for each destination.
     */
    for (i = 0; i < consumer_count; i++) {

        output_block = core_vector_at(&output_blocks, i);

        biosal_assembly_arc_block_init(output_block, ephemeral_memory, concrete_self->kmer_length,
                        &concrete_self->codec);

        biosal_assembly_arc_block_reserve(output_block, reservation);
    }

    size = core_vector_size(input_arcs);

    /*
     * Classify every arc in the input block
     * and put them in output blocks.
     */

#ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG
    printf("ClassifyArcs arc_count= %d\n", size);

#endif

    CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

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

        arc = core_vector_at(input_arcs, i);

        kmer = biosal_assembly_arc_source(arc);

        consumer_index = biosal_dna_kmer_store_index(kmer, consumer_count,
                        concrete_self->kmer_length, &concrete_self->codec,
                        ephemeral_memory);

        output_block = core_vector_at(&output_blocks, consumer_index);

        /*
         * Make a copy of the arc and copy it.
         * It will be freed
         */

        biosal_assembly_arc_block_add_arc_copy(output_block, arc,
                        concrete_self->kmer_length, &concrete_self->codec,
                        ephemeral_memory);
    }

    /*
     * Input arcs are not needed anymore.
     */
    biosal_assembly_arc_block_destroy(&input_block, ephemeral_memory);

    CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

    /*
     * Finally, send these output blocks to consumers.
     */

    maximum_pending_requests = 0;
    maximum_buffer_length = 0;

    /*
     * Figure out the maximum buffer length tor
     * messages.
     */
    for (i = 0; i < consumer_count; i++) {

        output_block = core_vector_at(&output_blocks, i);
        new_count = biosal_assembly_arc_block_pack_size(output_block, concrete_self->kmer_length,
                    &concrete_self->codec);

        if (new_count > maximum_buffer_length) {
            maximum_buffer_length = new_count;
        }
    }

#if 0
    printf("POOL_BALANCE %d\n",
                    core_memory_pool_profile_balance_count(ephemeral_memory));
#endif

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

        output_block = core_vector_at(&output_blocks, i);
        output_arcs = biosal_assembly_arc_block_get_arcs(output_block);
        arc_count = core_vector_size(output_arcs);

        /*
         * Don't send an empty message.
         */
        if (arc_count > 0) {

            /*
             * Allocation is not required because new_count <= maximum_buffer_length
             */
            new_count = biosal_assembly_arc_block_pack_size(output_block, concrete_self->kmer_length,
                    &concrete_self->codec);

            new_buffer = thorium_actor_allocate(self, maximum_buffer_length);

            CORE_DEBUGGER_ASSERT(new_count <= maximum_buffer_length);

            biosal_assembly_arc_block_pack(output_block, new_buffer, concrete_self->kmer_length,
                    &concrete_self->codec);

            thorium_message_init(&new_message, ACTION_ASSEMBLY_PUSH_ARC_BLOCK,
                    new_count, new_buffer);

            consumer = core_vector_at_as_int(&concrete_self->consumers, i);

            /*
             * Send the message.
             */
            thorium_actor_send(self, consumer, &new_message);
            thorium_message_destroy(&new_message);

            /* update event counters for control.
             */
            bucket = core_vector_at(&concrete_self->pending_requests, i);
            ++(*bucket);
            ++concrete_self->active_requests;

            if (*bucket > maximum_pending_requests) {
                maximum_pending_requests = *bucket;
            }

            if (*bucket > concrete_self->maximum_pending_request_count) {
                ++concrete_self->consumer_count_above_threshold;
            }
        }

        CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

#if 0
        printf("i = %d\n", i);
#endif

        /*
         * Destroy output block.
         */
        biosal_assembly_arc_block_destroy(output_block,
                    ephemeral_memory);

        CORE_DEBUGGER_LEAK_CHECK_DOUBLE_FREE(ephemeral_memory);
        CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));
    }

    core_vector_destroy(&output_blocks);

    CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

    CORE_DEBUGGER_LEAK_CHECK_DOUBLE_FREE(ephemeral_memory);

    /*
     * Check if a response must be sent now.
     */

    ++concrete_self->received_blocks;
    concrete_self->source = source;

    /*
     * Only send a direct reply if there is enough memory.
     *
     * As long as maximum_pending_requests is lower than maximum_pending_request_count,
     * there is still space for at least one additional request.
     */
    if (maximum_pending_requests < concrete_self->maximum_pending_request_count
            && core_memory_has_enough_bytes()) {

        thorium_actor_send_empty(self, concrete_self->source,
                    ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY);
    } else {

        concrete_self->producer_is_waiting = 1;
    }

    CORE_DEBUGGER_LEAK_DETECTION_END(ephemeral_memory, classify_arcs);
}
Beispiel #8
0
int biosal_input_command_pack_unpack(struct biosal_input_command *self, void *buffer,
                int operation, struct core_memory_pool *memory, struct biosal_dna_codec *codec)
{
    struct core_packer packer;
    int offset;
    int64_t entries;
    struct biosal_dna_sequence dna_sequence;
    struct biosal_dna_sequence *other_sequence;
    int bytes;
    int i;

#ifdef BIOSAL_INPUT_COMMAND_DEBUG
    if (1 || operation == CORE_PACKER_OPERATION_UNPACK) {
        printf("DEBUG ENTRY biosal_input_command_pack_unpack operation %d\n",
                        operation);
    }
#endif

    offset = 0;

    core_packer_init(&packer, operation, buffer);

    core_packer_process(&packer, &self->store_name, sizeof(self->store_name));
    core_packer_process(&packer, &self->store_first, sizeof(self->store_first));
    core_packer_process(&packer, &self->store_last, sizeof(self->store_last));

    /* TODO remove this line
     */

    /*
    if (operation == CORE_PACKER_OPERATION_UNPACK) {
        core_vector_init(&self->entries, sizeof(struct biosal_dna_sequence));
    }

    return core_packer_get_byte_count(&packer);
*/

#ifdef BIOSAL_INPUT_COMMAND_DEBUG
    if (1 || operation == CORE_PACKER_OPERATION_UNPACK) {
        printf("DEBUG biosal_input_command_pack_unpack offset after packing stuff %d\n",
                    offset);
    }
#endif

    /* do the vector too
     * process the count.
     * then, process every read.
     */

    if (operation == CORE_PACKER_OPERATION_PACK
                    || operation == CORE_PACKER_OPERATION_PACK_SIZE) {
        entries = core_vector_size(&self->entries);
    } else if (operation == CORE_PACKER_OPERATION_UNPACK) {

        core_vector_init(&self->entries, sizeof(struct biosal_dna_sequence));

        core_vector_set_memory_pool(&self->entries, memory);
    }

    /* 1. entries
     */
    core_packer_process(&packer, &entries, sizeof(entries));

    offset = core_packer_get_byte_count(&packer);
    core_packer_destroy(&packer);

#ifdef BIOSAL_INPUT_COMMAND_DEBUG
    printf("DEBUG biosal_input_command_pack_unpack operation %d entries %d offset %d\n",
                    operation, entries, offset);
#endif

    /* 2. get the entries
     */
    if (operation == CORE_PACKER_OPERATION_UNPACK) {

        while (entries--) {
            bytes = biosal_dna_sequence_unpack(&dna_sequence,
                            (char *) buffer + offset,
                            memory, codec);

#ifdef BIOSAL_INPUT_COMMAND_DEBUG
            printf("DEBUG unpacking DNA sequence, used %d bytes\n",
                            bytes);
#endif
            offset += bytes;

            core_vector_push_back(&self->entries, &dna_sequence);
        }
    } else if (operation == CORE_PACKER_OPERATION_PACK) {

        i = 0;
        while (entries--) {
            other_sequence = (struct biosal_dna_sequence *)core_vector_at(&self->entries,
                            i++);
            bytes = biosal_dna_sequence_pack(other_sequence,
                            (char *) buffer + offset,
                            codec);
            offset += bytes;

#ifdef BIOSAL_INPUT_COMMAND_DEBUG
            printf("DEBUG packing DNA sequence, used %d bytes, sum %d\n",
                            bytes, offset);
#endif
        }
    } else if (operation == CORE_PACKER_OPERATION_PACK_SIZE) {

        i = 0;
        while (entries--) {
            other_sequence = (struct biosal_dna_sequence *)core_vector_at(&self->entries,
                            i++);
            bytes = biosal_dna_sequence_pack_size(other_sequence, codec);

            offset += bytes;

#ifdef BIOSAL_INPUT_COMMAND_DEBUG
            printf("DEBUG dry run DNA sequence, used %d bytes, sum %d\n",
                            bytes, offset);
#endif
        }
    }

#ifdef BIOSAL_INPUT_COMMAND_DEBUG
    printf("DEBUG biosal_input_command_pack_unpack operation %d final offset %d\n",
                    operation, offset);

    if (operation == CORE_PACKER_OPERATION_UNPACK) {
        printf("DEBUG biosal_input_command_pack_unpack unpacked %d entries\n",
                        (int)core_vector_size(&self->entries));
    }
#endif

    return offset;
}