struct biosal_assembly_vertex *biosal_assembly_graph_store_find_vertex(struct thorium_actor *self, struct biosal_dna_kmer *kmer) { struct core_memory_pool *ephemeral_memory; struct biosal_assembly_graph_store *concrete_self; char *sequence; struct biosal_dna_kmer storage_kmer; char *key; struct biosal_assembly_vertex *canonical_vertex; ephemeral_memory = thorium_actor_get_ephemeral_memory(self); concrete_self = thorium_actor_concrete_actor(self); sequence = core_memory_pool_allocate(ephemeral_memory, concrete_self->kmer_length + 1); biosal_dna_kmer_get_sequence(kmer, sequence, concrete_self->kmer_length, &concrete_self->transport_codec); biosal_dna_kmer_init(&storage_kmer, sequence, &concrete_self->storage_codec, ephemeral_memory); key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes); biosal_dna_kmer_pack_store_key(&storage_kmer, key, concrete_self->kmer_length, &concrete_self->storage_codec, ephemeral_memory); canonical_vertex = core_map_get(&concrete_self->table, key); #ifdef CORE_DEBUGGER_ASSERT if (canonical_vertex == NULL) { printf("not found Seq = %s name %d kmerlength %d key_length %d hash %" PRIu64 "\n", sequence, thorium_actor_name(self), concrete_self->kmer_length, concrete_self->key_length_in_bytes, biosal_dna_kmer_hash(&storage_kmer, concrete_self->kmer_length, &concrete_self->storage_codec)); } #endif CORE_DEBUGGER_ASSERT(canonical_vertex != NULL); core_memory_pool_free(ephemeral_memory, sequence); core_memory_pool_free(ephemeral_memory, key); biosal_dna_kmer_destroy(&storage_kmer, ephemeral_memory); return canonical_vertex; }
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 }
void biosal_dna_kmer_reverse_complement_self(struct biosal_dna_kmer *self, int kmer_length, struct biosal_dna_codec *codec, struct core_memory_pool *memory) { #ifdef BIOSAL_DNA_CODEC_HAS_REVERSE_COMPLEMENT_IMPLEMENTATION biosal_dna_codec_reverse_complement_in_place(codec, kmer_length, self->encoded_data); #else char *sequence; sequence = core_memory_pool_allocate(memory, kmer_length + 1); biosal_dna_kmer_get_sequence(self, sequence, kmer_length, codec); #ifdef BIOSAL_DNA_KMER_DEBUG printf("DEBUG %p before %s\n", (void *)self, sequence); #endif biosal_dna_helper_reverse_complement_in_place(sequence); #ifdef BIOSAL_DNA_KMER_DEBUG printf("DEBUG %p after %s\n", (void *)self, sequence); #endif biosal_dna_kmer_destroy(self, memory); biosal_dna_kmer_init(self, sequence, codec, memory); core_memory_pool_free(memory, sequence); sequence = NULL; #endif }
void biosal_dna_kmer_init_random(struct biosal_dna_kmer *sequence, int kmer_length, struct biosal_dna_codec *codec, struct core_memory_pool *memory) { char *dna; int i; int code; dna = (char *)core_memory_pool_allocate(memory, kmer_length + 1); for (i = 0; i < kmer_length; i++) { code = rand() % 4; if (code == 0) { dna[i] = 'A'; } else if (code == 1) { dna[i] = 'T'; } else if (code == 2) { dna[i] = 'C'; } else if (code == 3) { dna[i] = 'G'; } } dna[kmer_length] = '\0'; biosal_dna_kmer_init(sequence, dna, codec, memory); core_memory_pool_free(memory, dna); }
/* \see http://www.malcolmmclean.site11.com/www/MpiTutorial/MPIStatus.html */ int thorium_mpi1_pt2pt_transport_receive(struct thorium_transport *self, struct thorium_message *message) { struct thorium_mpi1_pt2pt_transport *concrete_self; char *buffer; int count; int source; int destination; int tag; int flag; MPI_Status status; int result; concrete_self = thorium_transport_get_concrete_transport(self); source = MPI_ANY_SOURCE; tag = DUMMY_TAG; /* get return value */ result = MPI_Iprobe(source, tag, concrete_self->comm, &flag, &status); if (result != MPI_SUCCESS) { return 0; } if (!flag) { return 0; } /* get return value */ result = MPI_Get_count(&status, concrete_self->datatype, &count); if (result != MPI_SUCCESS) { return 0; } /* actually allocate (slab allocator) a buffer with count bytes ! */ buffer = core_memory_pool_allocate(self->inbound_message_memory_pool, count * sizeof(char)); source = status.MPI_SOURCE; /* get return value */ result = MPI_Recv(buffer, count, concrete_self->datatype, source, tag, concrete_self->comm, &status); if (result != MPI_SUCCESS) { return 0; } destination = self->rank; /* * Prepare the message. The worker will be -1 to tell the thorium * code that this is not a worker buffer. */ thorium_message_init_with_nodes(message, count, buffer, source, destination); return 1; }
void biosal_dna_kmer_init_copy(struct biosal_dna_kmer *self, struct biosal_dna_kmer *other, int kmer_length, struct core_memory_pool *memory, struct biosal_dna_codec *codec) { int encoded_length; encoded_length = biosal_dna_codec_encoded_length(codec, kmer_length); self->encoded_data = core_memory_pool_allocate(memory, encoded_length); core_memory_copy(self->encoded_data, other->encoded_data, encoded_length); }
int core_vector_pack_unpack(struct core_vector *self, void *buffer, int operation) { struct core_packer packer; int64_t bytes; int size; struct core_memory_pool *memory; core_packer_init(&packer, operation, buffer); core_packer_process(&packer, &self->size, sizeof(self->size)); #ifdef CORE_VECTOR_DEBUG printf("DEBUG core_vector_pack_unpack operation %d size %d\n", operation, self->size); #endif core_packer_process(&packer, &self->element_size, sizeof(self->element_size)); #ifdef CORE_VECTOR_DEBUG printf("DEBUG core_vector_pack_unpack operation %d element_size %d\n", operation, self->element_size); #endif if (operation == CORE_PACKER_OPERATION_UNPACK) { size = self->size; memory = self->memory; core_vector_init(self, self->element_size); /* * Restore attributes. */ self->size = size; self->maximum_size = self->size; self->memory = memory; if (self->size > 0) { self->data = core_memory_pool_allocate(self->memory, self->maximum_size * self->element_size); ++self->profile_allocate_calls; } else { self->data = NULL; } } if (self->size > 0) { core_packer_process(&packer, self->data, self->size * self->element_size); } bytes = core_packer_get_byte_count(&packer); core_packer_destroy(&packer); return bytes; }
void test_allocator(struct core_memory_pool *memory) { int i; int size; void *pointer; struct core_vector vector; struct core_timer timer; uint64_t elapsed; i = 1000000; size = 45; core_vector_init(&vector, sizeof(void *)); core_timer_init(&timer); core_timer_start(&timer); while (i--) { if (memory != NULL) { pointer = core_memory_pool_allocate(memory, size); } else { pointer = core_memory_allocate(size, -1); } core_vector_push_back(&vector, &pointer); } core_timer_stop(&timer); elapsed = core_timer_get_elapsed_nanoseconds(&timer); if (memory == NULL) { printf("Not using memory pool... "); } else { printf("Using memory pool... "); } printf("Elapsed : %" PRIu64 " milliseconds\n", elapsed / 1000 / 1000); size = core_vector_size(&vector); for (i = 0; i < size; ++i) { pointer = core_vector_at_as_void_pointer(&vector, i); if (memory != NULL) { core_memory_pool_free(memory, pointer); } else { core_memory_free(pointer, -1); } } core_vector_destroy(&vector); core_timer_destroy(&timer); }
void biosal_dna_kmer_print(struct biosal_dna_kmer *self, int kmer_length, struct biosal_dna_codec *codec, struct core_memory_pool *memory) { char *dna_sequence; dna_sequence = core_memory_pool_allocate(memory, kmer_length + 1); biosal_dna_codec_decode(codec, kmer_length, self->encoded_data, dna_sequence); printf("KMER length: %d nucleotides, sequence: %s hash %" PRIu64 "\n", kmer_length, dna_sequence, biosal_dna_kmer_canonical_hash(self, kmer_length, codec, memory)); core_memory_pool_free(memory, dna_sequence); dna_sequence = NULL; }
void core_vector_reserve(struct core_vector *self, int64_t size) { void *new_data; int64_t old_byte_count; int64_t new_byte_count; #ifdef CORE_VECTOR_DEBUG printf("DEBUG core_vector_reserve %p %d buckets current_size %d\n", (void *)self, (int)size, (int)self->size); #endif if (size <= self->maximum_size) { return; } new_byte_count = size * self->element_size; old_byte_count = self->size * self->element_size; #ifdef CORE_VECTOR_DEBUG printf("DEBUG core_vector_reserve old_byte_count %d new_byte_count %d\n", old_byte_count, new_byte_count); #endif new_data = core_memory_pool_allocate(self->memory, new_byte_count); ++self->profile_allocate_calls; #ifdef CORE_VECTOR_DEBUG printf("DEBUG size %d old %p new %p\n", (int)self->size, (void *)self->data, (void *)new_data); #endif /* * copy old data */ if (self->size > 0) { core_memory_copy(new_data, self->data, old_byte_count); core_memory_pool_free(self->memory, self->data); ++self->profile_free_calls; self->data = NULL; } self->data = new_data; self->maximum_size = size; }
void *thorium_worker_allocate(struct thorium_worker *self, size_t count) { void *buffer; int all; int metadata_size; metadata_size = THORIUM_MESSAGE_METADATA_SIZE; all = count + metadata_size; /* use slab allocator to allocate buffer... */ buffer = (char *)core_memory_pool_allocate(&self->outbound_message_memory_pool, all * sizeof(char)); self->zero_copy_buffer = buffer; return buffer; }
void biosal_dna_kmer_init_mock(struct biosal_dna_kmer *sequence, int kmer_length, struct biosal_dna_codec *codec, struct core_memory_pool *memory) { char *dna; int i; dna = (char *)core_memory_pool_allocate(memory, kmer_length + 1); for (i = 0; i < kmer_length; i++) { dna[i] = 'A'; } dna[kmer_length] = '\0'; biosal_dna_kmer_init(sequence, dna, codec, memory); core_memory_pool_free(memory, dna); }
void core_string_rotate_path(char *sequence, int length, int rotation, int kmer_length, struct core_memory_pool *pool) { char *buffer; /* * Impossible. */ if (length < kmer_length) { return; } /* * Simplify the rotation */ rotation %= length; buffer = core_memory_pool_allocate(pool, length); /* * Algorithm: * * 1. Copy (l - r) from old @ r to new @ 0 * 2. Copy (r - k + 1) from old @ (k - 1) to new @ (l - r) (only if (r - k + 1 > 0)) * 3. Copy (k - 1) from new @ 0 to new @ (l - k + 1) */ core_memory_copy(buffer + 0, sequence + rotation, (length - rotation)); /* * Copy the middle * */ if ((rotation - kmer_length + 1) > 0) core_memory_copy(buffer + (length - rotation), sequence + (kmer_length - 1), (rotation - kmer_length + 1)); core_memory_copy(buffer + (length - kmer_length + 1), buffer + 0, (kmer_length - 1)); /* * Copy the new sequence. */ core_memory_copy(sequence, buffer, length); core_memory_pool_free(pool, buffer); }
void thorium_actor_send_range_vector(struct thorium_actor *actor, struct core_vector *actors, int tag, struct core_vector *vector) { struct thorium_message message; int count; void *buffer; struct core_memory_pool *ephemeral_memory; ephemeral_memory = thorium_actor_get_ephemeral_memory(actor); count = core_vector_pack_size(vector); buffer = core_memory_pool_allocate(ephemeral_memory, count); core_vector_pack(vector, buffer); thorium_message_init(&message, tag, count, buffer); thorium_actor_send_range(actor, actors, &message); thorium_message_destroy(&message); core_memory_pool_free(ephemeral_memory, buffer); }
/* #define BIOSAL_DNA_SEQUENCE_DEBUG */ void biosal_dna_kmer_init(struct biosal_dna_kmer *sequence, char *data, struct biosal_dna_codec *codec, struct core_memory_pool *memory) { int encoded_length; int kmer_length; if (data == NULL) { sequence->encoded_data = NULL; kmer_length = 0; } else { kmer_length = strlen(data); encoded_length = biosal_dna_codec_encoded_length(codec, kmer_length); sequence->encoded_data = core_memory_pool_allocate(memory, encoded_length); biosal_dna_codec_encode(codec, kmer_length, data, sequence->encoded_data); } }
int biosal_dna_kmer_pack_unpack(struct biosal_dna_kmer *sequence, void *buffer, int operation, int kmer_length, struct core_memory_pool *memory, struct biosal_dna_codec *codec) { struct core_packer packer; int offset; int encoded_length; core_packer_init(&packer, operation, buffer); /* don't pack the kmer length... */ #if 0 core_packer_process(&packer, kmer_length, sizeof(kmer_length)); #endif encoded_length = biosal_dna_codec_encoded_length(codec, kmer_length); /* encode in 2 bits instead ! */ if (operation == CORE_PACKER_OPERATION_UNPACK) { if (kmer_length > 0) { sequence->encoded_data = core_memory_pool_allocate(memory, encoded_length); } else { sequence->encoded_data = NULL; } } if (kmer_length > 0) { core_packer_process(&packer, sequence->encoded_data, encoded_length); } offset = core_packer_get_byte_count(&packer); core_packer_destroy(&packer); return offset; }
/* * Returns 1 if the message was multiplexed. * * This is O(1) in regard to the number of thorium nodes. */ int thorium_message_multiplexer_multiplex(struct thorium_message_multiplexer *self, struct thorium_message *message) { /* * If buffer is full, use thorium_node_send_with_transport * * get count * * if count is below or equal to the threshold * multiplex the message. * return 1 * * return 0 */ int count; int current_size; int maximum_size; int action; struct core_memory_pool *pool; void *new_buffer; int new_count; void *buffer; int destination_node; int destination_actor; int new_size; int required_size; struct thorium_multiplexed_buffer *real_multiplexed_buffer; uint64_t time; int next_node_in_route; int source_node; int current_node; #ifdef DEBUG_MULTIPLEXER thorium_printf("multiplex\n"); thorium_message_print(message); #endif if (CORE_BITMAP_GET_FLAG(self->flags, FLAG_DISABLED)) { return 0; } action = thorium_message_action(message); CORE_DEBUGGER_ASSERT(action != ACTION_INVALID); #ifdef THORIUM_MULTIPLEXER_USE_ACTIONS_TO_SKIP /* * Don't multiplex already-multiplexed messages. */ if (thorium_multiplexer_policy_is_action_to_skip(self->policy, action)) { return 0; } #endif #ifdef CONFIG_MULTIPLEXER_USE_DECISION_MAKER thorium_message_multiplexer_update_timeout(self); #endif ++self->original_message_count; count = thorium_message_count(message); destination_node = thorium_message_destination_node(message); source_node = message->routing_source; current_node = self->node->name; next_node_in_route = thorium_router_get_next_rank_in_route(&self->router, source_node, current_node, destination_node); /* thorium_message_print(message); thorium_printf("router: source_node %d current_node %d next_node_in_route %d" " destination_node %d\n", source_node, current_node, next_node_in_route, destination_node); */ #ifdef CONFIG_USE_TOPOLOGY_AWARE_AGGREGATION /* * The next node in the route for this message is * next_node_in_route. */ destination_node = next_node_in_route; #endif CORE_DEBUGGER_ASSERT(source_node >= 0); real_multiplexed_buffer = core_vector_at(&self->buffers, destination_node); CORE_DEBUGGER_ASSERT(real_multiplexed_buffer != NULL); required_size = thorium_multiplexed_buffer_required_size(real_multiplexed_buffer, count); buffer = thorium_message_buffer(message); destination_actor = thorium_message_destination(message); #ifdef DEBUG_MULTIPLEXER thorium_printf("DEBUG multiplex count %d required_size %d action %x\n", count, required_size, action); #endif /* * Don't multiplex non-actor messages. */ if (destination_actor == THORIUM_ACTOR_NOBODY) { return 0; } #ifdef CORE_DEBUGGER_ASSERT if (real_multiplexed_buffer == NULL) { thorium_printf("Error action %d destination_node %d destination_actor %d\n", action, destination_node, destination_actor); } #endif current_size = thorium_multiplexed_buffer_current_size(real_multiplexed_buffer); maximum_size = thorium_multiplexed_buffer_maximum_size(real_multiplexed_buffer); /* * Don't multiplex large messages. */ if (required_size > maximum_size) { #ifdef DEBUG_MULTIPLEXER thorium_printf("too large required_size %d maximum_size %d\n", required_size, maximum_size); #endif return 0; } /* thorium_printf("MULTIPLEX_MESSAGE\n"); */ new_size = current_size + required_size; /* * Flush now if there is no space left for the <required_size> bytes */ if (new_size > maximum_size) { #ifdef DEBUG_MULTIPLEXER thorium_printf("thorium_message_multiplexer: must FLUSH thorium_message_multiplexer_multiplex required_size %d new_size %d maximum_size %d\n", required_size, new_size, maximum_size); #endif thorium_message_multiplexer_flush(self, destination_node, FORCE_YES_SIZE); current_size = thorium_multiplexed_buffer_current_size(real_multiplexed_buffer); CORE_DEBUGGER_ASSERT(current_size == 0); } time = core_timer_get_nanoseconds(&self->timer); /* * If the buffer is empty before adding the data, it means that it is not * in the list of buffers with content and it must be added. */ if (current_size == 0) { thorium_multiplexed_buffer_set_time(real_multiplexed_buffer, time); #ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT core_set_add(&self->buffers_with_content, &destination_node); #endif /* * Add it to the timeline. */ #ifdef THORIUM_MULTIPLEXER_USE_TREE core_red_black_tree_add_key_and_value(&self->timeline, &time, &destination_node); #elif defined(THORIUM_MULTIPLEXER_USE_HEAP) core_binary_heap_insert(&self->timeline, &time, &destination_node); #elif defined(THORIUM_MULTIPLEXER_USE_QUEUE) core_queue_enqueue(&self->timeline, &destination_node); #endif } /* * The allocation of buffer is lazy. * The current worker is an exporter of small message for the destination * "destination_node". */ if (thorium_multiplexed_buffer_buffer(real_multiplexed_buffer) == NULL) { pool = thorium_worker_get_outbound_message_memory_pool(self->worker); new_count = self->buffer_size_in_bytes + THORIUM_MESSAGE_METADATA_SIZE; new_buffer = core_memory_pool_allocate(pool, new_count); thorium_multiplexed_buffer_set_buffer(real_multiplexed_buffer, new_buffer); } /* thorium_printf("DEBUG worker_latency %d ns\n", thorium_worker_latency(self->worker)); */ thorium_multiplexed_buffer_append(real_multiplexed_buffer, count, buffer, time); /* * Try to flush. This only flushes something if the buffer is full. */ if (thorium_message_multiplexer_buffer_is_ready(self, real_multiplexed_buffer)) { /* * Try to flush here too. This is required in order to satisfy the * technical requirement of a DOA limit. * * Obviously, don't flush if there is some outbound traffic congestion. * Otherwise, there will be too many messages on the network. */ if (!thorium_worker_has_outbound_traffic_congestion(self->worker)) { thorium_message_multiplexer_flush(self, destination_node, FORCE_YES_SIZE); } } /* * Verify invariant. */ CORE_DEBUGGER_ASSERT(thorium_multiplexed_buffer_current_size(real_multiplexed_buffer)<= maximum_size); /* * Inject the buffer into the worker too. */ return 1; }
void biosal_assembly_graph_store_get_starting_vertex(struct thorium_actor *self, struct thorium_message *message) { struct biosal_assembly_graph_store *concrete_self; struct biosal_dna_kmer transport_kmer; struct biosal_dna_kmer storage_kmer; struct core_memory_pool *ephemeral_memory; struct thorium_message new_message; int new_count; void *new_buffer; char *sequence; void *storage_key; struct biosal_assembly_vertex *vertex; concrete_self = thorium_actor_concrete_actor(self); ephemeral_memory = thorium_actor_get_ephemeral_memory(self); while (core_map_iterator_has_next(&concrete_self->iterator)) { storage_key = NULL; vertex = NULL; core_map_iterator_next(&concrete_self->iterator, (void **)&storage_key, (void **)&vertex); /* * Skip the vertex if it does have the status * BIOSAL_VERTEX_FLAG_USED. */ if (biosal_assembly_vertex_get_flag(vertex, BIOSAL_VERTEX_FLAG_USED)) { continue; } CORE_DEBUGGER_ASSERT(storage_key != NULL); #ifdef BIOSAL_ASSEMBLY_GRAPH_STORE_DEBUG_GET_STARTING_VERTEX printf("From storage\n"); biosal_assembly_vertex_print(vertex); core_debugger_examine(storage_key, concrete_self->key_length_in_bytes); #endif biosal_dna_kmer_init_empty(&storage_kmer); biosal_dna_kmer_unpack(&storage_kmer, storage_key, concrete_self->kmer_length, ephemeral_memory, &concrete_self->storage_codec); #ifdef BIOSAL_ASSEMBLY_GRAPH_STORE_DEBUG_GET_STARTING_VERTEX printf("DEBUG starting kmer Storage kmer hash %" PRIu64 "\n", biosal_dna_kmer_hash(&storage_kmer, concrete_self->kmer_length, &concrete_self->storage_codec)); biosal_dna_kmer_print(&storage_kmer, concrete_self->kmer_length, &concrete_self->storage_codec, ephemeral_memory); #endif sequence = core_memory_pool_allocate(ephemeral_memory, concrete_self->kmer_length + 1); biosal_dna_kmer_get_sequence(&storage_kmer, sequence, concrete_self->kmer_length, &concrete_self->storage_codec); #ifdef BIOSAL_ASSEMBLY_GRAPH_STORE_DEBUG_GET_STARTING_VERTEX printf("SEQUENCE %s\n", sequence); #endif biosal_dna_kmer_init(&transport_kmer, sequence, &concrete_self->transport_codec, ephemeral_memory); new_count = biosal_dna_kmer_pack_size(&transport_kmer, concrete_self->kmer_length, &concrete_self->transport_codec); new_buffer = thorium_actor_allocate(self, new_count); biosal_dna_kmer_pack(&transport_kmer, new_buffer, concrete_self->kmer_length, &concrete_self->transport_codec); #ifdef BIOSAL_ASSEMBLY_GRAPH_STORE_DEBUG_GET_STARTING_VERTEX printf("Packed version:\n"); core_debugger_examine(new_buffer, new_count); printf("TRANSPORT Kmer new_count %d\n", new_count); biosal_dna_kmer_print(&transport_kmer, concrete_self->kmer_length, &concrete_self->transport_codec, ephemeral_memory); #endif thorium_message_init(&new_message, ACTION_ASSEMBLY_GET_STARTING_KMER_REPLY, new_count, new_buffer); thorium_actor_send_reply(self, &new_message); thorium_message_destroy(&new_message); biosal_dna_kmer_destroy(&transport_kmer, ephemeral_memory); core_memory_pool_free(ephemeral_memory, sequence); biosal_dna_kmer_destroy(&storage_kmer, ephemeral_memory); return; } /* * An empty reply means that the store has nothing more to yield. */ thorium_actor_send_reply_empty(self, ACTION_ASSEMBLY_GET_STARTING_KMER_REPLY); }
void biosal_assembly_graph_store_push_arc_block(struct thorium_actor *self, struct thorium_message *message) { struct biosal_assembly_graph_store *concrete_self; int size; int i; void *buffer; int count; struct biosal_assembly_arc_block input_block; struct biosal_assembly_arc *arc; struct core_memory_pool *ephemeral_memory; struct core_vector *input_arcs; char *sequence; void *key; #if 0 /* * Don't do anything to rule out that this is the problem. */ thorium_actor_send_reply_empty(self, ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY); return; #endif concrete_self = thorium_actor_concrete_actor(self); ephemeral_memory = thorium_actor_get_ephemeral_memory(self); sequence = core_memory_pool_allocate(ephemeral_memory, concrete_self->kmer_length + 1); ++concrete_self->received_arc_block_count; count = thorium_message_count(message); buffer = thorium_message_buffer(message); biosal_assembly_arc_block_init(&input_block, ephemeral_memory, concrete_self->kmer_length, &concrete_self->transport_codec); biosal_assembly_arc_block_unpack(&input_block, buffer, concrete_self->kmer_length, &concrete_self->transport_codec, ephemeral_memory); input_arcs = biosal_assembly_arc_block_get_arcs(&input_block); size = core_vector_size(input_arcs); if (!concrete_self->printed_arc_size) { printf("DEBUG ARC DELIVERY %d bytes, %d arcs\n", count, size); concrete_self->printed_arc_size = 1; } key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes); for (i = 0; i < size; i++) { arc = core_vector_at(input_arcs, i); #ifdef BIOSAL_ASSEMBLY_ADD_ARCS biosal_assembly_graph_store_add_arc(self, arc, sequence, key); #endif ++concrete_self->received_arc_count; } core_memory_pool_free(ephemeral_memory, key); biosal_assembly_arc_block_destroy(&input_block, ephemeral_memory); /* * * Add the arcs to the graph */ thorium_actor_send_reply_empty(self, ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY); core_memory_pool_free(ephemeral_memory, sequence); }
void biosal_assembly_graph_store_push_kmer_block(struct thorium_actor *self, struct thorium_message *message) { struct core_memory_pool *ephemeral_memory; struct biosal_dna_kmer_frequency_block block; struct biosal_assembly_vertex *bucket; void *packed_kmer; struct core_map_iterator iterator; struct biosal_assembly_graph_store *concrete_self; /*int tag;*/ void *key; struct core_map *kmers; struct biosal_dna_kmer kmer; void *buffer; int count; struct biosal_dna_kmer encoded_kmer; char *raw_kmer; int period; struct biosal_dna_kmer *kmer_pointer; int *frequency; ephemeral_memory = thorium_actor_get_ephemeral_memory(self); concrete_self = thorium_actor_concrete_actor(self); /*tag = thorium_message_action(message);*/ buffer = thorium_message_buffer(message); count = thorium_message_count(message); /* * Handler for PUSH_DATA */ biosal_dna_kmer_frequency_block_init(&block, concrete_self->kmer_length, ephemeral_memory, &concrete_self->transport_codec, 0); biosal_dna_kmer_frequency_block_unpack(&block, buffer, ephemeral_memory, &concrete_self->transport_codec); key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes); kmers = biosal_dna_kmer_frequency_block_kmers(&block); core_map_iterator_init(&iterator, kmers); period = 2500000; raw_kmer = core_memory_pool_allocate(thorium_actor_get_ephemeral_memory(self), concrete_self->kmer_length + 1); if (!concrete_self->printed_vertex_size) { printf("DEBUG VERTEX DELIVERY %d bytes\n", count); concrete_self->printed_vertex_size = 1; } while (core_map_iterator_has_next(&iterator)) { /* * add kmers to store */ core_map_iterator_next(&iterator, (void **)&packed_kmer, (void **)&frequency); /* Store the kmer in 2 bit encoding */ biosal_dna_kmer_init_empty(&kmer); biosal_dna_kmer_unpack(&kmer, packed_kmer, concrete_self->kmer_length, ephemeral_memory, &concrete_self->transport_codec); kmer_pointer = &kmer; if (concrete_self->codec_are_different) { /* * Get a copy of the sequence */ biosal_dna_kmer_get_sequence(kmer_pointer, raw_kmer, concrete_self->kmer_length, &concrete_self->transport_codec); biosal_dna_kmer_init(&encoded_kmer, raw_kmer, &concrete_self->storage_codec, thorium_actor_get_ephemeral_memory(self)); kmer_pointer = &encoded_kmer; } biosal_dna_kmer_pack_store_key(kmer_pointer, key, concrete_self->kmer_length, &concrete_self->storage_codec, thorium_actor_get_ephemeral_memory(self)); #ifdef BIOSAL_DEBUG_ISSUE_540 if (strcmp(raw_kmer, "AGCTGGTAGTCATCACCAGACTGGAACAG") == 0 || strcmp(raw_kmer, "CGCGATCTGTTGCTGGGCCTAACGTGGTA") == 0 || strcmp(raw_kmer, "TACCACGTTAGGCCCAGCAACAGATCGCG") == 0) { printf("Examine store key for %s\n", raw_kmer); core_debugger_examine(key, concrete_self->key_length_in_bytes); } #endif bucket = core_map_get(&concrete_self->table, key); if (bucket == NULL) { /* This is the first time that this kmer is seen. */ bucket = core_map_add(&concrete_self->table, key); biosal_assembly_vertex_init(bucket); #if 0 printf("DEBUG303 ADD_KEY"); biosal_dna_kmer_print(&encoded_kmer, concrete_self->kmer_length, &concrete_self->storage_codec, ephemeral_memory); #endif } if (concrete_self->codec_are_different) { biosal_dna_kmer_destroy(&encoded_kmer, thorium_actor_get_ephemeral_memory(self)); } biosal_dna_kmer_destroy(&kmer, ephemeral_memory); biosal_assembly_vertex_increase_coverage_depth(bucket, *frequency); if (concrete_self->received >= concrete_self->last_received + period) { printf("%s/%d received %" PRIu64 " kmers so far," " store has %" PRIu64 " canonical kmers, %" PRIu64 " kmers\n", thorium_actor_script_name(self), thorium_actor_name(self), concrete_self->received, core_map_size(&concrete_self->table), 2 * core_map_size(&concrete_self->table)); concrete_self->last_received = concrete_self->received; } concrete_self->received += *frequency; } core_memory_pool_free(ephemeral_memory, key); core_memory_pool_free(ephemeral_memory, raw_kmer); core_map_iterator_destroy(&iterator); biosal_dna_kmer_frequency_block_destroy(&block, thorium_actor_get_ephemeral_memory(self)); thorium_actor_send_reply_empty(self, ACTION_PUSH_KMER_BLOCK_REPLY); }
/* * Returns 1 if the message was demultiplexed. * * This is O(1) in regard to the number of thorium nodes. */ int thorium_message_multiplexer_demultiplex(struct thorium_message_multiplexer *self, struct thorium_message *message) { /* * Algorithm: * * get tag. * if tag is ACTION_MULTIPLEXER_MESSAGE * for every enclosed message * call thorium_node_prepare_received_message * call thorium_node_dispatch_message() * return 1 * * return 0 */ int count; char *buffer; struct thorium_message new_message; int new_count; void *new_buffer; int position; struct core_memory_pool *pool; int messages; int tag; int source_node; int destination_node; int current_node; int routing_destination; #ifdef DEBUG_MULTIPLEXER thorium_printf("demultiplex message\n"); thorium_message_print(message); #endif if (CORE_BITMAP_GET_FLAG(self->flags, FLAG_DISABLED)) { return 0; } tag = thorium_message_action(message); if (tag != ACTION_MULTIPLEXER_MESSAGE) { return 0; } /* thorium_printf("MULTIPLEXER demultiplex\n"); */ messages = 0; tracepoint(thorium_node, demultiplex_enter, self->node->name, self->node->tick, messages); source_node = thorium_message_source_node(message); destination_node = thorium_message_destination_node(message); /* * Remove the metadata from the count. */ thorium_message_remove_metadata_from_count(message); count = thorium_message_count(message); buffer = thorium_message_buffer(message); pool = thorium_worker_get_outbound_message_memory_pool(self->worker); position = 0; /* * Inject a message for each enclosed message. */ while (position < count) { core_memory_copy(&new_count, buffer + position, sizeof(new_count)); position += sizeof(new_count); new_buffer = core_memory_pool_allocate(pool, new_count); core_memory_copy(new_buffer, buffer + position, new_count); thorium_message_init_with_nodes(&new_message, new_count, new_buffer, source_node, destination_node); thorium_node_prepare_received_message(self->node, &new_message); /* * For these demultiplexed messages, there are 2 outcomes: * * 1) the message must be delivered locally; * 2) the message must be forward because this is a middle node in * the route. */ /* thorium_printf("demultiplex: \n"); thorium_message_print(&new_message); thorium_printf("\n"); */ /* * Mark the message for recycling. */ thorium_message_set_worker(&new_message, thorium_worker_name(self->worker)); #ifdef CORE_DEBUGGER_ASSERT_ENABLED if (thorium_message_action(&new_message) == ACTION_INVALID) { thorium_printf("Error invalid action DEMUL Multiplexer position %d count %d new_count %d\n", position, count, new_count); thorium_message_print(&new_message); } #endif CORE_DEBUGGER_ASSERT(thorium_message_action(&new_message) != ACTION_INVALID); /* thorium_printf("DEMULTIPLEX_MESSAGE\n"); */ /* thorium_printf("demultiplex, local delivery: \n"); thorium_message_print(&new_message); */ current_node = self->node->name; routing_destination = new_message.routing_destination; CORE_DEBUGGER_ASSERT(routing_destination >= 0); /* * This is a local delivery, nothing to see here. */ if (routing_destination == current_node) { thorium_worker_send_local_delivery(self->worker, &new_message); /* * Otherwise, get the next node in the route and send the * payload there since we can not do anything with it here. */ } else { /* * Export the message to another node. * To do this, use an exporter worker. */ thorium_worker_send_for_multiplexer(self->worker, &new_message); } /* thorium_message_destroy(&new_message); */ position += new_count; ++messages; } CORE_DEBUGGER_ASSERT(messages > 0); #ifdef DEBUG_MULTIPLEXER thorium_printf("thorium_message_multiplexer_demultiplex %d messages\n", messages); #endif tracepoint(thorium_node, demultiplex_exit, self->node->name, self->node->tick, messages); return 1; }
void biosal_assembly_graph_store_mark_vertex_as_visited(struct thorium_actor *self, struct thorium_message *message) { struct biosal_assembly_graph_store *concrete_self; char *buffer; int source; int path_index; char *sequence; struct core_memory_pool *ephemeral_memory; struct biosal_dna_kmer kmer; struct biosal_dna_kmer storage_kmer; struct biosal_assembly_vertex *canonical_vertex; int position; void *key; int force; force = 1; position = 0; concrete_self = thorium_actor_concrete_actor(self); source = thorium_message_source(message); buffer = thorium_message_buffer(message); ephemeral_memory = thorium_actor_get_ephemeral_memory(self); /* * Get the kmer. */ biosal_dna_kmer_init_empty(&kmer); position += biosal_dna_kmer_unpack(&kmer, buffer, concrete_self->kmer_length, ephemeral_memory, &concrete_self->transport_codec); sequence = core_memory_pool_allocate(ephemeral_memory, concrete_self->kmer_length + 1); biosal_dna_kmer_get_sequence(&kmer, sequence, concrete_self->kmer_length, &concrete_self->transport_codec); biosal_dna_kmer_init(&storage_kmer, sequence, &concrete_self->storage_codec, ephemeral_memory); /* * Get store key */ key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes); biosal_dna_kmer_pack_store_key(&storage_kmer, key, concrete_self->kmer_length, &concrete_self->storage_codec, ephemeral_memory); /* Get vertex. */ canonical_vertex = core_map_get(&concrete_self->table, key); biosal_dna_kmer_destroy(&kmer, ephemeral_memory); biosal_dna_kmer_destroy(&storage_kmer, ephemeral_memory); core_memory_pool_free(ephemeral_memory, key); core_memory_pool_free(ephemeral_memory, sequence); position += thorium_message_unpack_int(message, position, &path_index); /* * At this point, mark the vertex with flag BIOSAL_VERTEX_FLAG_USED * so that any other actor that attempt to grab it will have to communicate * with the actor. */ /* * This is a good idea to always update with the last one. */ if (force || !biosal_assembly_vertex_get_flag(canonical_vertex, BIOSAL_VERTEX_FLAG_USED)) { biosal_assembly_graph_store_mark_as_used(self, canonical_vertex, source, path_index); } #if 0 #endif thorium_actor_send_reply_empty(self, ACTION_MARK_VERTEX_AS_VISITED_REPLY); }
struct core_simple_queue_item *core_simple_queue_allocate_item(struct core_simple_queue *self) { #ifdef USE_BLOCK_ALLOCATION struct core_simple_queue_item *item; int unit_size; int count; int block_size; int i; struct core_simple_queue_item *allocation; /* * Use the linked list of garbage-collected items. */ if (self->garbage_ != NULL) { item = self->garbage_; /* Move the garbage pointer. */ self->garbage_ = self->garbage_->next_; item->data_ = ((char *)item) + sizeof(struct core_simple_queue_item); item->next_ = NULL; return item; } unit_size = sizeof(struct core_simple_queue_item) + self->bytes_per_unit_; block_size = 32768; count = block_size / unit_size; block_size = count * unit_size; allocation = core_memory_pool_allocate(self->pool_, block_size); allocation->next_ = self->allocations_; self->allocations_ = allocation; #ifdef DEBUG_QUEUE printf("generate %d items from %d bytes\n", count - 1, block_size); #endif /* * Generate items in garbage list; */ i = 0; /* * Skip the first one since it is used for tracking allocations. */ ++i; while (i < count) { item = (void *)(((char *)allocation) + i * unit_size); item->next_ = self->garbage_; self->garbage_ = item; ++i; } /* * Recursive call. * There is at most one recursive call. */ return core_simple_queue_allocate_item(self); #else int unit_size; struct core_simple_queue_item *item; unit_size = sizeof(struct core_simple_queue_item) + self->bytes_per_unit_; item = core_memory_pool_allocate(self->pool_, unit_size); item->next_ = NULL; item->data_ = ((char *)item) + sizeof(struct core_simple_queue_item); return item; #endif }
void biosal_assembly_graph_store_print(struct thorium_actor *self) { struct core_map_iterator iterator; struct biosal_dna_kmer kmer; void *key; struct biosal_assembly_vertex *value; int coverage; char *sequence; struct biosal_assembly_graph_store *concrete_self; int maximum_length; int length; struct core_memory_pool *ephemeral_memory; ephemeral_memory = thorium_actor_get_ephemeral_memory(self); concrete_self = thorium_actor_concrete_actor(self); core_map_iterator_init(&iterator, &concrete_self->table); printf("map size %d\n", (int)core_map_size(&concrete_self->table)); maximum_length = 0; while (core_map_iterator_has_next(&iterator)) { core_map_iterator_next(&iterator, (void **)&key, (void **)&value); biosal_dna_kmer_init_empty(&kmer); biosal_dna_kmer_unpack(&kmer, key, concrete_self->kmer_length, thorium_actor_get_ephemeral_memory(self), &concrete_self->storage_codec); length = biosal_dna_kmer_length(&kmer, concrete_self->kmer_length); /* printf("length %d\n", length); */ if (length > maximum_length) { maximum_length = length; } biosal_dna_kmer_destroy(&kmer, thorium_actor_get_ephemeral_memory(self)); } /* printf("MAx length %d\n", maximum_length); */ sequence = core_memory_pool_allocate(ephemeral_memory, maximum_length + 1); sequence[0] = '\0'; core_map_iterator_destroy(&iterator); core_map_iterator_init(&iterator, &concrete_self->table); while (core_map_iterator_has_next(&iterator)) { core_map_iterator_next(&iterator, (void **)&key, (void **)&value); biosal_dna_kmer_init_empty(&kmer); biosal_dna_kmer_unpack(&kmer, key, concrete_self->kmer_length, thorium_actor_get_ephemeral_memory(self), &concrete_self->storage_codec); biosal_dna_kmer_get_sequence(&kmer, sequence, concrete_self->kmer_length, &concrete_self->storage_codec); coverage = biosal_assembly_vertex_coverage_depth(value); printf("Sequence %s Coverage %d\n", sequence, coverage); biosal_dna_kmer_destroy(&kmer, thorium_actor_get_ephemeral_memory(self)); } core_map_iterator_destroy(&iterator); core_memory_pool_free(ephemeral_memory, sequence); }