summaryrefslogtreecommitdiff
path: root/benchmarks/CUDA/MUM/mummergpu.cu
diff options
context:
space:
mode:
Diffstat (limited to 'benchmarks/CUDA/MUM/mummergpu.cu')
-rw-r--r--benchmarks/CUDA/MUM/mummergpu.cu1259
1 files changed, 1259 insertions, 0 deletions
diff --git a/benchmarks/CUDA/MUM/mummergpu.cu b/benchmarks/CUDA/MUM/mummergpu.cu
new file mode 100644
index 0000000..43b3ff5
--- /dev/null
+++ b/benchmarks/CUDA/MUM/mummergpu.cu
@@ -0,0 +1,1259 @@
+// Includes, system
+#define ulong4 uint4
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+
+// includes, kernels
+#include <common.cu>
+
+#include <mummergpu.h>
+#include <mummergpu_kernel.cu>
+
+#define BLOCKSIZE 256
+
+#define CUDA_SAFE_CALL( call) do { \
+ cudaError err = call; \
+ if( cudaSuccess != err) { \
+ fprintf(stderr, "Cuda error in file '%s' in line %i : %s.\n", \
+ __FILE__, __LINE__, cudaGetErrorString( err) ); \
+ exit(EXIT_FAILURE); \
+ } } while (0)
+
+
+////////////////////////////////////////////////////////////////////////////////
+// declaration, forward
+void runTest( int argc, char** argv);
+
+extern "C"
+void computeGold(MatchResults* results,
+ char* refstr,
+ char* queries,
+ int* queryAddrs,
+ int* queryLengths,
+ PixelOfNode* nodeTexture,
+ PixelOfChildren* childrenTexture,
+ int numQueries,
+ int mismatch_length,
+ int rc);
+
+extern "C"
+void getReferenceString(const char * filename, char** refstr, size_t* reflen);
+
+extern "C"
+void createTreeTexture(const char * filename,
+ PixelOfNode** nodeTexture, PixelOfChildren** childrenTexture,
+ unsigned int* width, unsigned int* height,
+ AuxiliaryNodeData** aux_data,
+ int* num_nodes,
+ const char * dotfilename,
+ const char * texfilename);
+
+extern "C"
+void getQueriesTexture(int qfile,
+ char** queryTexture,
+ size_t* queryLength,
+ int** queryAddrs,
+ char*** queryNames,
+ int** queryLengths,
+ unsigned int* numQueries,
+ size_t device_memory_avail,
+ int min_match_length,
+ bool rc);
+
+void printAlignments(char* ref,
+ ReferencePage* page,
+ char* query,
+ int qrylen,
+ int nodeid,
+ int qrypos,
+ int edge_depth,
+ int min_match,
+ bool rc,
+ bool forwardcoordinates);
+
+int countLeafNodes(int nodeid);
+
+// Timer management
+struct Timer_t
+{
+ struct timeval start_m;
+ struct timeval end_m;
+};
+
+void createTimer(unsigned int * timer)
+{
+ unsigned int * ptr = (unsigned int *) malloc(sizeof(struct Timer_t));
+ memset(ptr, 0, sizeof(struct Timer_t));
+
+ *timer = (unsigned int)(unsigned long long) ptr;
+}
+
+void startTimer(unsigned int ptr)
+{
+ gettimeofday(&(((struct Timer_t *)ptr)->start_m), NULL);
+}
+
+void stopTimer(unsigned int ptr)
+{
+ gettimeofday(&(((struct Timer_t *)ptr)->end_m), NULL);
+}
+
+float getTimerValue(unsigned int ptr)
+{
+ Timer_t * timer = (Timer_t*) ptr;
+
+ if (timer == NULL)
+ {
+ fprintf(stderr, "Uninitialized timer!!!\n");
+ return 0.0;
+ }
+
+ if (timer->end_m.tv_sec == 0) { stopTimer(ptr); }
+
+ return (float) (1000.0 * (timer->end_m.tv_sec - timer->start_m.tv_sec)
+ + (0.001 * (timer->end_m.tv_usec - timer->start_m.tv_usec)));
+}
+
+void deleteTimer(unsigned int ptr)
+{
+ free((Timer_t *)ptr);
+}
+
+extern "C"
+int createReference(const char* fromFile, Reference* ref)
+{
+ if (!fromFile || !ref)
+ return -1;
+
+ getReferenceString(fromFile, &(ref->str), &(ref->len));
+
+ return 0;
+}
+
+extern "C"
+int destroyReference(Reference* ref)
+{
+ free(ref->h_node_tex_array);
+ free(ref->h_children_tex_array);
+ free(ref->str);
+ free(ref->h_ref_tex_array);
+ free(ref->aux_data);
+ ref->str = NULL;
+ ref->len = 0;
+
+ return 0;
+}
+
+extern "C"
+int createQuerySet(const char* fromFile, QuerySet* queries)
+{
+
+ fprintf(stderr, "Opening %s...\n", fromFile);
+ int qfile = open(fromFile, O_RDONLY);
+
+ if (qfile == -1)
+ {
+ fprintf(stderr, "Can't open %s: %d\n", fromFile, errno);
+ exit (1);
+ }
+
+ queries->qfile = qfile;
+
+ return 0;
+}
+
+extern "C"
+int destroyQuerySet(QuerySet* queries)
+{
+
+ if (queries->qfile)
+ close(queries->qfile);
+
+ return 0;
+}
+
+extern "C"
+void printStringForError(int err)
+{
+
+}
+
+extern "C"
+int createMatchContext(Reference* ref,
+ QuerySet* queries,
+ MatchResults* matches,
+ MUMMERGPU_OPTIONS options,
+ int min_match_length,
+ char* stats_file,
+ bool reverse,
+ bool forwardreverse,
+ bool forwardcoordinates,
+ bool showQueryLength,
+ MatchContext* ctx)
+{
+
+ ctx->queries = queries;
+ ctx->ref = ref;
+ ctx->full_ref = ref->str;
+ ctx->full_ref_len = ref->len;
+
+ // break out options here
+ ctx->on_cpu = options & ON_CPU;
+ ctx->min_match_length = min_match_length;
+ ctx->stats_file = stats_file;
+ ctx->reverse = reverse;
+ ctx->forwardreverse = forwardreverse;
+ ctx->forwardcoordinates = forwardcoordinates;
+ ctx->show_query_length = showQueryLength;
+ return 0;
+}
+
+extern "C"
+int destroyMatchContext(MatchContext* ctx)
+{
+ free(ctx->full_ref);
+ //destroyReference(ctx->ref);
+ destroyQuerySet(ctx->queries);
+ return 0;
+}
+
+void buildReferenceTexture(Reference* ref, char* full_ref, size_t begin, size_t end)
+{
+ fprintf(stderr, "Building reference texture...\n");
+
+
+
+ PixelOfNode* nodeTexture = NULL;
+ PixelOfChildren * childrenTexture = NULL;
+
+ unsigned int height = 0;
+ unsigned int width = 0;
+
+ AuxiliaryNodeData* aux_data = NULL;
+ int num_nodes;
+
+ ref->len = end - begin + 3;
+ ref->str = (char*)malloc(ref->len);
+ ref->str[0] = 's';
+ strncpy(ref->str + 1, full_ref + begin, ref->len - 3);
+ strcpy(ref->str + ref->len - 2, "$");
+ createTreeTexture(ref->str,
+ &nodeTexture,
+ &childrenTexture,
+ &width, &height,
+ &aux_data,
+ &num_nodes,
+ NULL,
+ NULL);
+
+ ref->h_node_tex_array = nodeTexture;
+ ref->h_children_tex_array = childrenTexture;
+ ref->tex_width = width;
+ ref->tex_height = height;
+
+ ref->aux_data = aux_data;
+ ref->num_nodes = num_nodes;
+
+ ref->bytes_on_board = width * height * (sizeof(PixelOfNode) + sizeof(PixelOfChildren));
+
+ unsigned int refpitch = ref->pitch = 65536;
+ int numrows = ceil(ref->len / ((float)refpitch));
+ int blocksize = 4;
+ numrows += blocksize;
+
+ ref->h_ref_tex_array = (char *) malloc(numrows*refpitch);
+
+ ref->bytes_on_board += numrows*refpitch;
+
+ int z_max = numrows * refpitch;
+ for (int z = 0; z < z_max; z++) { ref->h_ref_tex_array[z] = 'Z'; }
+
+ int x, y;
+ int maxx = 0, maxy = 0;
+
+ size_t reflen = ref->len;
+ char* refstr = ref->str;
+
+
+ int block_dim = refpitch * blocksize;
+ for (int i = 0; i < reflen; i++)
+ {
+ int bigx = i % (block_dim);
+ int bigy = i / (block_dim);
+
+ y = bigy*blocksize+bigx%blocksize;
+ x = bigx / blocksize;
+
+ // printf("%d: (%d,%d)=%c\n", i, x, y, refstr[i]);
+
+ assert(x < refpitch);
+ assert(y < numrows);
+
+ ref->h_ref_tex_array[y*refpitch+x] = refstr[i];
+
+ if (x > maxx) { maxx = x; }
+ if (y > maxy) { maxy = y; }
+ }
+
+ if ((maxx >= refpitch) || (maxy >= numrows))
+ {
+ fprintf(stderr, "ERROR: maxx: %d refpitch: %d, maxy: %d numrows: %d\n",
+ maxx, refpitch, maxy, numrows);
+
+ exit(1);
+ }
+
+}
+
+void loadReferenceTexture(MatchContext* ctx)
+{
+ Reference* ref = ctx->ref;
+ int numrows = ceil(ref->len / ((float)ref->pitch));
+ int blocksize = 4;
+ numrows += blocksize;
+
+ cudaChannelFormatDesc refTextureDesc =
+ cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindSigned);
+
+ if (!ctx->on_cpu)
+ {
+ unsigned int toboardtimer = 0;
+ createTimer(&toboardtimer);
+ startTimer(toboardtimer);
+
+ fprintf(stderr, "allocating reference texture\n");
+ CUDA_SAFE_CALL(cudaMallocArray( (cudaArray**)(&ref->d_ref_tex_array),
+ &refTextureDesc,
+ ref->pitch,
+ numrows));
+
+ //ref->bytes_on_board += ref->pitch * numrows;
+
+ CUDA_SAFE_CALL(cudaMemcpyToArray( (cudaArray*)(ref->d_ref_tex_array),
+ 0,
+ 0,
+ ref->h_ref_tex_array,
+ numrows*ref->pitch,
+ cudaMemcpyHostToDevice));
+
+ reftex.addressMode[0] = cudaAddressModeClamp;
+ reftex.addressMode[1] = cudaAddressModeClamp;
+ reftex.filterMode = cudaFilterModePoint;
+ reftex.normalized = false;
+
+ CUDA_SAFE_CALL(cudaBindTextureToArray( reftex, (cudaArray*)ref->d_ref_tex_array, refTextureDesc));
+
+ stopTimer(toboardtimer);
+ ctx->statistics.t_moving_tree_pages += getTimerValue(toboardtimer);
+ deleteTimer(toboardtimer);
+ }
+ else
+ {
+ ref->d_ref_tex_array = NULL;
+ }
+
+ fprintf(stderr,"done\n");
+
+}
+
+void unloadReferenceTexture(Reference* ref)
+{
+ CUDA_SAFE_CALL(cudaUnbindTexture( reftex ) );
+ CUDA_SAFE_CALL(cudaFreeArray((cudaArray*)(ref->d_ref_tex_array)));
+ ref->d_ref_tex_array = NULL;
+}
+
+
+//loads a tree and text for [begin, end) in the reference
+void loadReference(MatchContext* ctx)
+{
+
+ Reference* ref = ctx->ref;
+
+ //ref->bytes_on_board = 0;
+
+ loadReferenceTexture(ctx);
+
+ if (!ctx->on_cpu)
+ {
+ unsigned int toboardtimer = 0;
+ createTimer(&toboardtimer);
+ startTimer(toboardtimer);
+
+ cudaChannelFormatDesc nodeTextureDesc =
+ cudaCreateChannelDesc(32, 32, 32, 32, cudaChannelFormatKindUnsigned);
+
+ CUDA_SAFE_CALL( cudaMallocArray( (cudaArray**)(&ref->d_node_tex_array),
+ &nodeTextureDesc,
+ ref->tex_width,
+ ref->tex_height ));
+
+ //ref->bytes_on_board += ref->tex_width * ref->tex_height * (sizeof(PixelOfNode));
+
+ CUDA_SAFE_CALL( cudaMemcpyToArray( (cudaArray*)(ref->d_node_tex_array),
+ 0,
+ 0,
+ ref->h_node_tex_array,
+ ref->tex_width * ref->tex_height * sizeof(PixelOfNode),
+ cudaMemcpyHostToDevice));
+
+ nodetex.addressMode[0] = cudaAddressModeClamp;
+ nodetex.addressMode[1] = cudaAddressModeClamp;
+ nodetex.filterMode = cudaFilterModePoint;
+ nodetex.normalized = false; // access with normalized texture coordinates
+
+ CUDA_SAFE_CALL( cudaBindTextureToArray( nodetex,
+ (cudaArray*)ref->d_node_tex_array,
+ nodeTextureDesc));
+
+ cudaChannelFormatDesc childrenTextureDesc =
+ cudaCreateChannelDesc(32, 32, 32, 32, cudaChannelFormatKindUnsigned);
+
+ CUDA_SAFE_CALL( cudaMallocArray( (cudaArray**)(&ref->d_children_tex_array),
+ &childrenTextureDesc,
+ ref->tex_width,
+ ref->tex_height ));
+
+ //ref->bytes_on_board += ref->tex_width * ref->tex_height * sizeof(PixelOfNode);
+
+ CUDA_SAFE_CALL( cudaMemcpyToArray((cudaArray*)(ref->d_children_tex_array),
+ 0,
+ 0,
+ ref->h_children_tex_array,
+ ref->tex_width * ref->tex_height * sizeof(PixelOfChildren),
+ cudaMemcpyHostToDevice));
+
+ childrentex.addressMode[0] = cudaAddressModeClamp;
+ childrentex.addressMode[1] = cudaAddressModeClamp;
+ childrentex.filterMode = cudaFilterModePoint;
+ childrentex.normalized = false; // access with normalized texture coordinates
+
+ CUDA_SAFE_CALL( cudaBindTextureToArray( childrentex,
+ (cudaArray*)(ref->d_children_tex_array),
+ childrenTextureDesc));
+ fprintf(stderr, "done\n");
+
+ stopTimer(toboardtimer);
+ ctx->statistics.t_moving_tree_pages += getTimerValue(toboardtimer);
+ deleteTimer(toboardtimer);
+ }
+ else
+ {
+ ref->d_node_tex_array = NULL;
+ ref->d_children_tex_array = NULL;
+ }
+}
+
+void unloadReference(MatchContext* ctx)
+{
+ Reference* ref = ctx->ref;
+
+ CUDA_SAFE_CALL(cudaUnbindTexture( nodetex ) );
+ CUDA_SAFE_CALL(cudaFreeArray((cudaArray*)(ref->d_node_tex_array)));
+ ref->d_node_tex_array = NULL;
+
+ CUDA_SAFE_CALL(cudaUnbindTexture( childrentex ) );
+ CUDA_SAFE_CALL(cudaFreeArray((cudaArray*)(ref->d_children_tex_array)));
+ ref->d_children_tex_array = NULL;
+
+ unloadReferenceTexture(ctx->ref);
+}
+
+
+
+void loadQueries(MatchContext* ctx)
+{
+ unsigned int toboardtimer = 0;
+ createTimer(&toboardtimer);
+ startTimer(toboardtimer);
+
+ QuerySet* queries = ctx->queries;
+ queries->bytes_on_board = 0;
+
+ unsigned int numQueries = queries->count;
+
+ if (!ctx->on_cpu)
+ {
+ fprintf(stderr, "loadQueries on GPU: Allocating device memory for queries...\n");
+
+ CUDA_SAFE_CALL( cudaMalloc((void**) &queries->d_tex_array, queries->texlen));
+
+ queries->bytes_on_board += queries->texlen;
+
+ CUDA_SAFE_CALL( cudaMemcpy((void*) queries->d_tex_array,
+ queries->h_tex_array + queries->h_addrs_tex_array[0],
+ queries->texlen,
+ cudaMemcpyHostToDevice));
+
+ CUDA_SAFE_CALL( cudaMalloc((void**) &queries->d_addrs_tex_array,
+ numQueries * sizeof(int)));
+
+ queries->bytes_on_board += numQueries * sizeof(int);
+
+ CUDA_SAFE_CALL( cudaMemcpy((void*) queries->d_addrs_tex_array,
+ queries->h_addrs_tex_array,
+ numQueries * sizeof(int),
+ cudaMemcpyHostToDevice));
+
+ CUDA_SAFE_CALL( cudaMalloc((void**) &queries->d_lengths_array,
+ numQueries * sizeof(int)));
+
+ queries->bytes_on_board += numQueries * sizeof(int);
+
+ CUDA_SAFE_CALL( cudaMemcpy((void*) queries->d_lengths_array,
+ queries->h_lengths_array,
+ numQueries * sizeof(int),
+ cudaMemcpyHostToDevice));
+
+ fprintf(stderr, "loadQueries on GPU: allocated %ld bytes done\n", 2 * numQueries*sizeof(int) + queries->texlen);
+ }
+ else
+ {
+ queries->d_addrs_tex_array = NULL;
+ queries->d_tex_array = NULL;
+ queries->d_lengths_array = NULL;
+ fprintf(stderr, "loadQueries on CPU: allocated %ld bytes done\n", numQueries*sizeof(int) + queries->texlen);
+ }
+
+ stopTimer(toboardtimer);
+ ctx->statistics.t_to_board += getTimerValue(toboardtimer);
+ deleteTimer(toboardtimer);
+}
+
+void unloadQueries(MatchContext* ctx)
+{
+ QuerySet* queries = ctx->queries;
+
+ CUDA_SAFE_CALL(cudaFree(queries->d_tex_array));
+ queries->d_tex_array = NULL;
+
+ CUDA_SAFE_CALL(cudaFree(queries->d_addrs_tex_array));
+ queries->d_addrs_tex_array = NULL;
+
+ CUDA_SAFE_CALL(cudaFree(queries->d_lengths_array));
+ queries->d_lengths_array = NULL;
+
+ queries->bytes_on_board = 0;
+}
+
+void loadResultBuffer(MatchContext* ctx)
+{
+ unsigned int numQueries = ctx->queries->count;
+
+ assert (numQueries);
+
+ int match_length = ctx->min_match_length;
+
+ unsigned int numCoords = 0;
+
+ numCoords = ctx->queries->texlen - numQueries * (match_length + 1);
+
+ ctx->results.numCoords = numCoords;
+
+ fprintf(stderr, "Allocating result array for %d queries (%d bytes) ...",numQueries, numCoords*sizeof(MatchCoord) );
+ ctx->results.h_match_coords = (MatchCoord*) calloc( numCoords, sizeof(MatchCoord));
+
+ if (!ctx->on_cpu)
+ {
+ unsigned int toboardtimer = 0;
+ createTimer(&toboardtimer);
+ startTimer(toboardtimer);
+
+ ctx->results.bytes_on_board = 0;
+
+ CUDA_SAFE_CALL( cudaMalloc( (void**) &ctx->results.d_match_coords,
+ numCoords * sizeof(MatchCoord)));
+ ctx->results.bytes_on_board += numCoords * sizeof(MatchCoord);
+
+ CUDA_SAFE_CALL( cudaMemset( (void*)ctx->results.d_match_coords, 0,
+ numCoords * sizeof(MatchCoord)));
+
+ stopTimer(toboardtimer);
+ ctx->statistics.t_to_board += getTimerValue(toboardtimer);
+ deleteTimer(toboardtimer);
+ }
+ else
+ {
+ ctx->results.d_match_coords = NULL;
+ }
+
+ fprintf(stderr, "done\n");
+}
+
+void unloadResultBuffer(MatchContext* ctx)
+{
+ CUDA_SAFE_CALL(cudaFree(ctx->results.d_match_coords));
+
+ ctx->results.bytes_on_board = 0;
+}
+
+
+void freeResults(MatchContext* ctx, ReferencePage pages[], unsigned int num_pages)
+{
+ for (int i = 0; i < num_pages; ++i)
+ {
+ free(pages[i].results.h_match_coords);
+ }
+}
+
+void transferResultsFromDevice(MatchContext* ctx)
+{
+ if (!ctx->on_cpu)
+ {
+ unsigned int fromboardtimer = 0;
+ createTimer(&fromboardtimer);
+ startTimer(fromboardtimer);
+
+ CUDA_SAFE_CALL(cudaMemcpy(ctx->results.h_match_coords,
+ ctx->results.d_match_coords,
+ ctx->results.numCoords * sizeof(MatchCoord),
+ cudaMemcpyDeviceToHost) );
+
+ stopTimer(fromboardtimer);
+ ctx->statistics.t_from_board += getTimerValue(fromboardtimer);
+ deleteTimer(fromboardtimer);
+ }
+
+}
+
+
+int flushOutput();
+int addToBuffer(char* string);
+
+inline int match_coord_addrs(int qryid, int qry_addrs, int match_length)
+{
+ return qry_addrs - qryid * (match_length + 1);
+}
+
+#define MAX_QUERY_LEN 8192
+
+struct packed_slot
+{
+ unsigned short page;
+ unsigned short qpos;
+ MatchCoord coord;
+};
+
+struct packed_slot_array
+{
+ packed_slot* slots;
+ unsigned int num_slots;
+};
+
+void addPackedOutput(MatchContext* ctx, packed_slot_array** curr_output, packed_slot_array slot_array[])
+{
+ unsigned int numQueries = ctx->queries->count;
+ if (*curr_output == NULL)
+ {
+ *curr_output = slot_array;
+ }
+ else
+ {
+ for (int i = 0; i < numQueries; i++)
+ {
+ if (slot_array[i].num_slots)
+ {
+ //packed_slot_array* slots = &(slot_array[i]);
+ (*curr_output)[i].slots = (packed_slot*)realloc((*curr_output)[i].slots,
+ ((*curr_output)[i].num_slots + slot_array[i].num_slots) * sizeof(packed_slot));
+ memcpy((*curr_output)[i].slots + (*curr_output)[i].num_slots,
+ slot_array[i].slots,
+ slot_array[i].num_slots * sizeof(packed_slot));
+ (*curr_output)[i].num_slots += slot_array[i].num_slots;
+ free(slot_array[i].slots);
+ }
+ }
+ free(slot_array);
+ }
+}
+
+char numbuffer[32];
+
+void printRCSlots(MatchContext * ctx, ReferencePage pages[], int qry, packed_slot_array * slots)
+{
+ char* h_tex_array = ctx->queries->h_tex_array;
+ int* h_addrs_tex_array = ctx->queries->h_addrs_tex_array;
+ int qrylen = ctx->queries->h_lengths_array[qry];
+
+ addToBuffer("> ");
+ addToBuffer(*(ctx->queries->h_names + qry));
+ addToBuffer(" Reverse");
+
+ if (ctx->show_query_length)
+ {
+ addToBuffer(" Len = ");
+ sprintf(numbuffer, "%d", qrylen);
+ addToBuffer(numbuffer);
+ }
+
+ addToBuffer("\n");
+
+ for (int j = 0; j < slots->num_slots; ++j)
+ {
+ packed_slot slot = slots->slots[j];
+
+ if (slot.coord.edge_match_length & FRMASK)
+ {
+ printAlignments(ctx->full_ref,
+ &(pages[slot.page]),
+ h_tex_array + h_addrs_tex_array[qry],
+ qrylen,
+ slot.coord.node,
+ slot.qpos,
+ (slot.coord.edge_match_length & FRUMASK),
+ ctx->min_match_length,
+ 1,
+ ctx->forwardcoordinates);
+ }
+ }
+}
+int FOO;
+void printForwardSlots(MatchContext * ctx, ReferencePage pages[], int qry, packed_slot_array * slots)
+{
+ char* h_tex_array = ctx->queries->h_tex_array;
+ int* h_addrs_tex_array = ctx->queries->h_addrs_tex_array;
+ int qrylen = ctx->queries->h_lengths_array[qry];
+
+ addToBuffer("> ");
+ addToBuffer(*(ctx->queries->h_names + qry));
+
+ if (ctx->show_query_length)
+ {
+ addToBuffer(" Len = ");
+ sprintf(numbuffer, "%d", qrylen);
+ addToBuffer(numbuffer);
+ }
+
+ addToBuffer("\n");
+
+ for (int j = 0; j < slots->num_slots; ++j)
+ {
+ packed_slot slot = slots->slots[j];
+ if (!(slot.coord.edge_match_length & FRMASK))
+ {
+ printAlignments(ctx->full_ref,
+ &(pages[slot.page]),
+ h_tex_array + h_addrs_tex_array[qry],
+ qrylen,
+ slot.coord.node,
+ slot.qpos,
+ slot.coord.edge_match_length,
+ ctx->min_match_length,
+ 0,
+ ctx->forwardcoordinates);
+ }
+ }
+ FOO += slots->num_slots;
+}
+
+void printPackedResults(MatchContext* ctx, ReferencePage pages[], packed_slot_array slot_array[])
+{
+ unsigned int numQueries = ctx->queries->count;
+ FOO = 0;
+ for (int qry = 0; qry < numQueries; qry++)
+ {
+ packed_slot_array* slots = &(slot_array[qry]);
+
+ if (ctx->reverse)
+ {
+ printRCSlots(ctx, pages, qry, slots);
+ }
+ else
+ {
+ printForwardSlots(ctx, pages, qry, slots);
+
+ if (ctx->forwardreverse)
+ {
+ printRCSlots(ctx, pages, qry, slots);
+ }
+ }
+ }
+ printf("FOO = %d\n", FOO);
+ flushOutput();
+}
+
+void packSlots(MatchContext* ctx, MatchResults* results, unsigned int page_num, packed_slot_array** slot_arrays, bool rc)
+{
+ unsigned int numQueries = ctx->queries->count;
+
+ int* h_addrs_tex_array = ctx->queries->h_addrs_tex_array;
+
+ int match_length = ctx->min_match_length;
+
+ *slot_arrays = (packed_slot_array*)calloc(numQueries, sizeof(packed_slot_array));
+
+ for (int i = 0; i < numQueries; i++)
+ {
+ int qlen;
+
+ if (i == numQueries - 1)
+ qlen = ctx->queries->texlen - h_addrs_tex_array[i] - match_length;
+ else
+ qlen = h_addrs_tex_array[i + 1] - h_addrs_tex_array[i] - match_length;
+
+ packed_slot* qslots = (packed_slot*)calloc(qlen, sizeof(packed_slot));
+ int filled = 0;
+ for (int p = 0; p < qlen; ++p)
+ {
+ MatchCoord* coords = results->h_match_coords;
+
+ int query_coord_begin = match_coord_addrs(i, h_addrs_tex_array[i], match_length);
+ int query_coord_end = i < numQueries - 1 ?
+ match_coord_addrs(i + 1, h_addrs_tex_array[i + 1], match_length) : results->numCoords;
+
+ int query_coord = query_coord_begin + p;
+
+ if ((query_coord < query_coord_end) &&
+ (coords[query_coord].node > 1) &&
+ (!(coords[query_coord].edge_match_length & FRMASK) == !rc))
+ {
+ packed_slot s;
+ s.page = page_num;
+ s.qpos = p;
+ s.coord = coords[query_coord];
+ qslots[filled++] = s;
+ }
+ }
+
+ if (filled)
+ {
+ packed_slot* pslots = (packed_slot*)calloc(filled, sizeof(packed_slot));
+ memcpy(pslots, qslots, (filled)*sizeof(packed_slot));
+
+ (*slot_arrays)[i].slots = pslots;
+ (*slot_arrays)[i].num_slots = filled;
+ }
+ else
+ {
+ (*slot_arrays)[i].slots = NULL;
+ (*slot_arrays)[i].num_slots = 0;
+ }
+
+ free(qslots);
+ }
+}
+
+int getQueryBlock(MatchContext* ctx, size_t device_mem_avail)
+{
+ QuerySet* queries = ctx->queries;
+ char * queryTex = NULL;
+ int* queryAddrs = NULL;
+ int* queryLengths = NULL;
+ unsigned int numQueries;
+ size_t queryLen;
+ char** names;
+
+ unsigned int queryreadtimer = 0;
+ createTimer(&queryreadtimer);
+ startTimer(queryreadtimer);
+
+ getQueriesTexture(queries->qfile,
+ &queryTex,
+ &queryLen,
+ &queryAddrs,
+ &names,
+ &queryLengths,
+ &numQueries,
+ device_mem_avail,
+ ctx->min_match_length,
+ ctx->reverse || ctx->forwardreverse);
+
+ stopTimer(queryreadtimer);
+ ctx->statistics.t_query_read += getTimerValue(queryreadtimer);
+ deleteTimer(queryreadtimer);
+
+ queries->h_tex_array = queryTex;
+ queries->count = numQueries;
+ queries->h_addrs_tex_array = queryAddrs;
+ queries->texlen = queryLen;
+ queries->h_names = names;
+ queries->h_lengths_array = queryLengths;
+
+ return numQueries;
+}
+
+
+void destroyQueryBlock(QuerySet* queries)
+{
+ free(queries->h_tex_array);
+ queries->h_tex_array = NULL;
+
+ for (int i = 0; i < queries->count; ++i)
+ free(queries->h_names[i]);
+
+ free(queries->h_names);
+
+ queries->count = 0;
+ queries->texlen = 0;
+
+ free(queries->h_addrs_tex_array);
+ queries->h_addrs_tex_array = NULL;
+
+ free(queries->h_lengths_array);
+ queries->h_lengths_array = NULL;
+}
+
+
+void writeStatisticsFile(MatchContext* ctx, char* stats_filename)
+{
+ if (!stats_filename)
+ return;
+
+ FILE* f = fopen(stats_filename, "w");
+
+ if (!f)
+ {
+ fprintf(stderr, "WARNING: could not open %s for writing\n", stats_filename);
+ return;
+ }
+
+ fprintf(f, "Total,%f\n", ctx->statistics.t_total);
+ fprintf(f, "Kernel,%f\n", ctx->statistics.t_kernel);
+ fprintf(f, "Print matches,%f\n", ctx->statistics.t_output);
+ fprintf(f, "Copy queries to GPU,%f\n", ctx->statistics.t_to_board);
+ fprintf(f, "Copy output from GPU,%f\n", ctx->statistics.t_from_board);
+ fprintf(f, "Copy suffix tree to GPU,%f\n", ctx->statistics.t_moving_tree_pages);
+ fprintf(f, "Read queries from disk,%f\n", ctx->statistics.t_query_read);
+ fprintf(f, "Suffix tree constructions,%f\n", ctx->statistics.t_construction);
+
+ fprintf(f, "Minimum substring length, %d\n", ctx->min_match_length);
+ fprintf(f, "Average query length, %f\n", ctx->statistics.bp_avg_query_length);
+ fclose(f);
+}
+
+int matchSubset(MatchContext* ctx,
+ int query_block_offset,
+ ReferencePage pages[],
+ unsigned int num_pages)
+{
+
+ loadQueries(ctx);
+ packed_slot_array* packed_slots = NULL;
+ for (unsigned int i = 0; i < num_pages; ++i)
+ {
+ ctx->ref = &(pages[i].ref);
+ loadReference(ctx);
+ loadResultBuffer(ctx);
+
+ unsigned int ktimer = 0;
+ createTimer(&ktimer);
+
+ unsigned int numQueries = ctx->queries->count;
+ int blocksize = (numQueries > BLOCKSIZE) ? BLOCKSIZE : numQueries;
+
+ dim3 dimBlock(blocksize,1,1);
+ dim3 dimGrid(ceil(numQueries/(float)BLOCKSIZE), 1, 1);
+
+ if (!ctx->on_cpu)
+ {
+ fprintf(stderr,"Using blocks of %d x %d x %d threads\n",
+ dimBlock.x, dimBlock.y, dimBlock.z);
+ fprintf(stderr,"Using a grid of %d x %d x %d blocks\n",
+ dimGrid.x, dimGrid.y, dimBlock.z);
+ fprintf(stderr,"Memory footprint is:\n\tqueries: %d\n\tref: %d\n\tresults: %d\n",
+ ctx->queries->bytes_on_board,
+ ctx->ref->bytes_on_board,
+ ctx->results.bytes_on_board);
+ }
+
+ startTimer(ktimer);
+
+ bool alignRC = ctx->reverse;
+
+ if (ctx->on_cpu)
+ {
+ if (alignRC)
+ {
+ computeGold(&ctx->results,
+ ctx->ref->str,
+ ctx->queries->h_tex_array,
+ ctx->queries->h_addrs_tex_array,
+ ctx->queries->h_lengths_array,
+ (PixelOfNode*)(ctx->ref->h_node_tex_array),
+ (PixelOfChildren*)(ctx->ref->h_children_tex_array),
+ ctx->queries->count,
+ ctx->min_match_length,
+ REVERSE);
+ }
+ else
+ {
+ computeGold(&ctx->results,
+ ctx->ref->str,
+ ctx->queries->h_tex_array,
+ ctx->queries->h_addrs_tex_array,
+ ctx->queries->h_lengths_array,
+ (PixelOfNode*)(ctx->ref->h_node_tex_array),
+ (PixelOfChildren*)(ctx->ref->h_children_tex_array),
+ ctx->queries->count,
+ ctx->min_match_length,
+ FORWARD);
+ }
+ }
+ else
+ {
+
+ if (alignRC)
+ {
+ mummergpuRCKernel<<< dimGrid, dimBlock, 0 >>>(ctx->results.d_match_coords,
+ ctx->queries->d_tex_array,
+ ctx->queries->d_addrs_tex_array,
+ ctx->queries->d_lengths_array,
+ numQueries,
+ ctx->min_match_length);
+ }
+ else
+ {
+ mummergpuKernel<<< dimGrid, dimBlock, 0 >>>(ctx->results.d_match_coords,
+ ctx->queries->d_tex_array,
+ ctx->queries->d_addrs_tex_array,
+ ctx->queries->d_lengths_array,
+ numQueries,
+ ctx->min_match_length);
+ }
+
+ }
+
+ cudaThreadSynchronize();
+
+ // check if kernel execution generated an error
+ cudaError_t err = cudaGetLastError();
+ if( cudaSuccess != err)
+ {
+ fprintf(stderr, "Kernel execution failed: %s.\n",
+ cudaGetErrorString(err));
+ exit(EXIT_FAILURE);
+ }
+
+ stopTimer(ktimer);
+
+ float ktime = getTimerValue(ktimer);
+ ctx->statistics.t_kernel += ktime;
+ fprintf(stderr,"kernel time= %f\n", ktime);
+ deleteTimer(ktimer);
+
+ transferResultsFromDevice(ctx);
+ pages[i].results = ctx->results;
+
+ packed_slot_array* packed;
+ packSlots(ctx, &(pages[i].results), i, &packed, ctx->reverse);
+ addPackedOutput(ctx, &packed_slots, packed);
+
+ // now compute the reverse matches.
+ if (ctx->forwardreverse)
+ {
+ unsigned int rctimer = 0;
+ createTimer(&rctimer);
+ startTimer(rctimer);
+
+ if (ctx->on_cpu)
+ {
+ computeGold(&ctx->results,
+ ctx->ref->str,
+ ctx->queries->h_tex_array,
+ ctx->queries->h_addrs_tex_array,
+ ctx->queries->h_lengths_array,
+ (PixelOfNode*)(ctx->ref->h_node_tex_array),
+ (PixelOfChildren*)(ctx->ref->h_children_tex_array),
+ ctx->queries->count,
+ ctx->min_match_length,
+ REVERSE);
+ }
+ else
+ {
+
+ mummergpuRCKernel<<< dimGrid, dimBlock, 0 >>>(ctx->results.d_match_coords,
+ ctx->queries->d_tex_array,
+ ctx->queries->d_addrs_tex_array,
+ ctx->queries->d_lengths_array,
+ numQueries,
+ ctx->min_match_length);
+ cudaThreadSynchronize();
+ }
+
+ stopTimer(rctimer);
+
+ float rctime = getTimerValue(rctimer);
+ ctx->statistics.t_kernel += rctime;
+ fprintf(stderr,"rc kernel time= %f\n", rctime);
+ deleteTimer(rctimer);
+
+ transferResultsFromDevice(ctx);
+ pages[i].results = ctx->results;
+
+ packed_slot_array* packed;
+ packSlots(ctx, &(pages[i].results), i, &packed, 1);
+ addPackedOutput(ctx, &packed_slots, packed);
+ }
+
+ free(pages[i].results.h_match_coords);
+ pages[i].results.h_match_coords = NULL;
+
+ unloadReference(ctx);
+ unloadResultBuffer(ctx);
+ }
+
+
+ unsigned int otimer = 0;
+ createTimer(&otimer);
+ startTimer(otimer);
+
+ printPackedResults(ctx, pages, packed_slots);
+
+ stopTimer(otimer);
+ ctx->statistics.t_output += getTimerValue(otimer);
+ deleteTimer(otimer);
+
+ for (int i = 0; i < ctx->queries->count; ++i)
+ {
+ free(packed_slots[i].slots);
+ }
+ free(packed_slots);
+
+ unloadQueries(ctx);
+ return 0;
+}
+
+#define BREATHING_ROOM (64 * 1024 * 1024)
+#define BASES_PER_TREE_PAGE 7500000
+#define CHUMP_CHANGE 1500000
+
+extern "C"
+int matchQueries(MatchContext* ctx)
+{
+ assert(sizeof(struct PixelOfNode) == sizeof(ulong4));
+ assert(sizeof(struct PixelOfChildren) == sizeof(ulong4));
+
+ ctx->statistics.t_kernel = 0.0;
+ ctx->statistics.t_output = 0.0;
+ ctx->statistics.t_to_board = 0.0;
+ ctx->statistics.t_from_board = 0.0;
+ ctx->statistics.t_moving_tree_pages = 0.0;
+ ctx->statistics.t_query_read = 0.0;
+ ctx->statistics.t_total = 0.0;
+ ctx->statistics.t_construction = 0.0;
+ ctx->statistics.bp_avg_query_length = 0.0;
+
+ unsigned int ttimer = 0;
+ createTimer(&ttimer);
+ startTimer(ttimer);
+
+ unsigned int ctimer = 0;
+ createTimer(&ctimer);
+ startTimer(ctimer);
+
+
+ unsigned int bases_in_ref = ctx->full_ref_len - 3;
+
+ unsigned int page_size = BASES_PER_TREE_PAGE < bases_in_ref ? BASES_PER_TREE_PAGE : bases_in_ref;
+ unsigned int num_reference_pages = bases_in_ref / page_size;
+
+ ReferencePage* pages = (ReferencePage*)calloc(num_reference_pages, sizeof(ReferencePage));
+
+ unsigned int page_overlap = MAX_QUERY_LEN + 1;
+
+
+ pages[0].begin = 1;
+ pages[0].end = pages[0].begin +
+ page_size +
+ ceil(page_overlap / 2.0) + 1; //the 1 is for the 's' at the beginning
+ pages[0].shadow_left = -1;
+ pages[0].id = 0;
+
+ buildReferenceTexture(&(pages[0].ref), ctx->full_ref, pages[0].begin, pages[0].end);
+
+ for (int i = 1; i < num_reference_pages - 1; ++i)
+ {
+ pages[i].begin = pages[i - 1].end - page_overlap;
+ pages[i].end = pages[i].begin + page_size + page_overlap;
+
+ pages[i - 1].shadow_right = pages[i].begin;
+ pages[i].shadow_left = pages[i-1].end;
+ pages[i].id = i;
+ buildReferenceTexture(&(pages[i].ref), ctx->full_ref, pages[i].begin, pages[i].end);
+ }
+
+ if (num_reference_pages > 1)
+ {
+ int last_page = num_reference_pages - 1;
+ pages[last_page].begin = pages[last_page - 1].end - page_overlap;
+ pages[last_page].end = ctx->full_ref_len - 1;
+ pages[last_page - 1].shadow_right = pages[last_page].begin;
+ pages[last_page].shadow_right = -1;
+ pages[last_page].shadow_left = pages[last_page - 1].end;
+ pages[last_page].id = last_page;
+ buildReferenceTexture(&(pages[last_page].ref),
+ ctx->full_ref,
+ pages[last_page].begin,
+ pages[last_page].end);
+ }
+
+ stopTimer(ctimer);
+ ctx->statistics.t_construction += getTimerValue(ctimer);
+ deleteTimer(ctimer);
+
+ cudaDeviceProp props;
+ if (!ctx->on_cpu)
+ {
+ int deviceCount = 0;
+ cudaGetDeviceCount(&deviceCount);
+
+ if (deviceCount != 1)
+ {
+ //fprintf(stderr, "Fatal error: no CUDA-capable device found, exiting\n");
+ //return -1;
+ }
+
+ cudaGetDeviceProperties(&props, 0);
+ fprintf(stderr, "Running under CUDA %d.%d\n", props.major, props.minor);
+ fprintf(stderr, "CUDA device has %d bytes of memory\n", props.totalGlobalMem);
+ }
+ else
+ {
+ props.totalGlobalMem = 804585472; // pretend we are on a 8800 GTX
+ }
+
+ size_t mem_avail = 0;
+ for (int i = 0; i < num_reference_pages; ++i)
+ {
+ mem_avail = max((unsigned int)pages[i].ref.bytes_on_board,
+ (unsigned int)mem_avail);
+ }
+
+ mem_avail = props.totalGlobalMem - mem_avail;
+
+ fprintf(stderr, "There are %d bytes left on the board\n", mem_avail);
+
+ mem_avail -= BREATHING_ROOM;
+
+ while (getQueryBlock(ctx, mem_avail))
+ {
+ matchSubset(ctx, 0, pages, num_reference_pages);
+ ctx->statistics.bp_avg_query_length = ctx->queries->texlen/(float)(ctx->queries->count) - 2;
+ destroyQueryBlock(ctx->queries);
+ cudaThreadExit();
+ }
+
+ for (int i = 0; i < num_reference_pages; ++i)
+ {
+ destroyReference(&(pages[i].ref));
+ }
+ free(pages);
+
+ stopTimer(ttimer);
+ ctx->statistics.t_total += getTimerValue(ttimer);
+ deleteTimer(ttimer);
+
+ writeStatisticsFile(ctx, ctx->stats_file);
+
+ return 0;
+}
+