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
void thorium_actor_pack_proxy_message(struct thorium_actor *self, struct thorium_message *message,
                int real_source)
{
    int real_tag;
    int count;
    int new_count;
    void *buffer;
    void *new_buffer;
    int offset;
    struct core_memory_pool *ephemeral_memory;

    /*
     * pack data in this order:
     *
     * - data (count bytes)
     * - real_source
     * - real_tag
     */
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);
    real_tag = thorium_message_action(message);
    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);

#ifdef DEBUG_BINOMIAL_TREE
    printf("DEBUG_BINOMIAL_TREE pack_proxy_message count %d source %d action %x\n", count,
                    thorium_actor_name(self),
                    real_tag);
    thorium_message_print(message);

#endif

    new_count = count + sizeof(real_source) + sizeof(real_tag);

    /* use slab allocator */
    new_buffer = core_memory_pool_allocate(ephemeral_memory, new_count);

#ifdef THORIUM_ACTOR_DEBUG
    printf("DEBUG12 core_memory_pool_allocate %p (pack proxy message)\n",
                    new_buffer);
#endif

    if (count > 0)
        core_memory_copy(new_buffer, buffer, count);

    offset = count;
    core_memory_copy((char *)new_buffer + offset, &real_source, sizeof(real_source));
    offset += sizeof(real_source);
    core_memory_copy((char *)new_buffer + offset, &real_tag, sizeof(real_tag));
    offset += sizeof(real_tag);

    thorium_message_init(message, ACTION_PROXY_MESSAGE, new_count, new_buffer);
    thorium_message_set_source(message, real_source);

#if 0
    /* free the old buffer
     */
    core_memory_free(buffer);
    buffer = NULL;
#endif
}
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 thorium_message_init_copy(struct thorium_message *self, struct thorium_message *old_message)
{
    thorium_message_init(self,
                    thorium_message_action(old_message),
                    thorium_message_count(old_message),
                    thorium_message_buffer(old_message));

    thorium_message_set_source(self,
                    thorium_message_source(old_message));
    thorium_message_set_destination(self,
                    thorium_message_destination(old_message));
}
Beispiel #5
0
void thorium_actor_unpack_proxy_message(struct thorium_actor *self,
                struct thorium_message *message)
{
    int new_count;
    int tag;
    int source;
    void *buffer;
    int offset;

    buffer = thorium_message_buffer(message);
    new_count = thorium_message_count(message);
    new_count -= sizeof(source);
    new_count -= sizeof(tag);

    offset = new_count;

    source = *(int *)((char *)buffer + offset);
    offset += sizeof(source);
    tag = *(int *)((char *)buffer + offset);

#ifdef DEBUG_BINOMIAL_TREE
    printf("DEBUG_BINOMIAL_TREE unpack_proxy_message real_count %d real_source %d real_action %x\n",
                    new_count, source, tag);
#endif

    /*
     * The action can not be ACTION_INVALID because it is invalid
     * by convention.
     */
    CORE_DEBUGGER_ASSERT(tag != ACTION_INVALID);

    offset += sizeof(tag);

    /*thorium_message_init(message, tag, new_count, buffer);*/

    /*
     * Change the tag, source, and count.
     */
    thorium_message_set_source(message, source);
    thorium_message_set_action(message, tag);
    thorium_message_set_count(message, new_count);

#if 0
    printf("DEBUG unpack_proxy_message... source %d tag %d count %d\n",
                    source, tag, new_count);
#endif
}
Beispiel #6
0
void thorium_message_init_with_nodes(struct thorium_message *self, int count, void *buffer, int source,
                int destination)
{
    int action;

    action = -1;

    thorium_message_init(self, action, count, buffer);

    /*
     * Initially assign the MPI source rank and MPI destination
     * rank for the actor source and actor destination, respectively.
     * Then, read the metadata and resolve the MPI rank from
     * that. The resolved MPI ranks should be the same in all cases
     */

    thorium_message_set_source(self, source);
    thorium_message_set_destination(self, destination);

    thorium_message_set_source_node(self, source);
    thorium_message_set_destination_node(self, destination);

    thorium_message_set_type(self, THORIUM_MESSAGE_TYPE_NODE_INBOUND);
}
Beispiel #7
0
void thorium_message_multiplexer_flush(struct thorium_message_multiplexer *self, int index, int force)
{
    char *buffer;
    struct thorium_message message;
    int tag;
    int count;
    int current_size;
    int maximum_size;
    struct thorium_multiplexed_buffer *multiplexed_buffer;
    int destination_node;
    /*
    int elapsed;
    int message_count;
    */

    if (CORE_BITMAP_GET_FLAG(self->flags, FLAG_DISABLED)) {
        return;
    }

#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
#ifdef CORE_DEBUGGER_ASSERT_ENABLED
    if (!(core_set_find(&self->buffers_with_content, &index))) {
        multiplexed_buffer = core_vector_at(&self->buffers, index);
        thorium_printf("index %d has no content\n", index);

        thorium_multiplexed_buffer_print(multiplexed_buffer);
    }
#endif

    CORE_DEBUGGER_ASSERT(core_set_find(&self->buffers_with_content, &index));
#endif

    multiplexed_buffer = core_vector_at(&self->buffers, index);
    current_size = thorium_multiplexed_buffer_current_size(multiplexed_buffer);
    maximum_size = thorium_multiplexed_buffer_maximum_size(multiplexed_buffer);

    /*
     * The buffer was still in the timeline, but it was flushed elsewhere.
     */
    if (current_size == 0) {
        return;

        /*
    if (force == FORCE_NO && current_size < maximum_size) {
        return;

    } else if (force == FORCE_YES_TIME) {
        elapsed = core_timer_get_nanoseconds(&self->timer) - multiplexed_buffer->timestamp_;

        if (elapsed < self->timeout_in_nanoseconds) {
            return;
        }
    } else if (force == FORCE_YES_DOA) {
        message_count = multiplexed_buffer->message_count_;

        if (message_count < self->degree_of_aggregation_limit) {
            return;
        }
        */
    }

#ifdef CORE_DEBUGGER_ASSERT_ENABLED
    if (current_size <= 0)
        thorium_printf("current_size %d maximum_size %d\n", current_size, maximum_size);
#endif

    CORE_DEBUGGER_ASSERT(current_size > 0);

    buffer = thorium_multiplexed_buffer_buffer(multiplexed_buffer);

    count = current_size + THORIUM_MESSAGE_METADATA_SIZE;

    tag = ACTION_MULTIPLEXER_MESSAGE;

    /*
     * This count does not include metadata for the final big message.
     *
     * Avoid this copy by using an array of pointers in the first place.
     */

    destination_node = index;

    thorium_message_init(&message, tag, count, buffer);
    thorium_message_set_destination(&message,
                    destination_node);
    thorium_message_set_source(&message,
            thorium_node_name(self->node));
    /*
     * Mark the message so that the buffer is eventually sent back here
     * for recycling.
     */
    thorium_message_set_worker(&message, thorium_worker_name(self->worker));

    thorium_message_write_metadata(&message);

#ifdef DEBUG_MULTIPLEXER_FLUSH
    thorium_printf("DEBUG_MULTIPLEXER thorium_message_multiplexer_flush index %d buffer %p force %d current_size %d maximum_size %d"
                    " destination_node %d\n",
                    index, buffer, force,
                    current_size, maximum_size,
                    thorium_message_destination_node(&message));

    thorium_printf("message in flush\n");
    thorium_multiplexed_buffer_print(multiplexed_buffer);
    thorium_message_print(&message);
#endif

    CORE_DEBUGGER_ASSERT_NOT_NULL(self->worker);

    /*
     * Make a copy of the buffer because the multiplexer does not have communication buffers.
     */
    thorium_worker_enqueue_outbound_message(self->worker, &message);

    /*
    thorium_printf("MULTIPLEXER FLUSH\n");
    */

    ++self->real_message_count;
    thorium_message_destroy(&message);

    thorium_multiplexed_buffer_reset(multiplexed_buffer);

#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
    core_set_delete(&self->buffers_with_content, &index);
#endif
}