Permalink
Browse files

Performance tunes and misc re-ordering

  • Loading branch information...
1 parent 22c9a45 commit 1682913a08f00600b6db3fbb10059fd11c0b596e @KristianLyng KristianLyng committed Oct 12, 2010
Showing with 91 additions and 76 deletions.
  1. +9 −4 Makefile
  2. +82 −72 main.c
View
@@ -1,12 +1,17 @@
TARGET=pathfinder
OBJS=main.o
-CFLAGS=-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wunused-parameter -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls -Wformat -O0 -g -fno-inline -DDIAGNOSTICS -Wextra -Wno-missing-field-initializers -Wno-sign-compare -fstack-protector-all -Werror
-%.o: %.c
+CFLAGS=-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wunused-parameter -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls -Wformat -g -Wextra -Wno-missing-field-initializers -Wno-sign-compare -Werror -O2
+
+# -O0 -pg -ftest-coverage -fprofile-arcs
+# -O2
+
+
+%.o: %.c Makefile
gcc $(CFLAGS) -c $^ -o $@
-$(TARGET): $(OBJS)
- gcc -o $(TARGET) $(OBJS)
+$(TARGET): $(OBJS) Makefile
+ gcc $(CFLAGS) -o $(TARGET) $(OBJS)
clean:
rm -rf $(OBJS) $(TARGET)
View
154 main.c
@@ -4,11 +4,14 @@
#include <assert.h>
#include <sys/time.h>
-#define RUNS 10000
+#define RUNS 100000
#define HEAD(q) (q->e[q->head])
#define TAIL(q) (q->e[q->tail])
+#define likely(x) __builtin_expect((x),1)
+#define unlikely(x) __builtin_expect((x),0)
+
struct grid_t {
int w, h;
int *ar;
@@ -28,68 +31,84 @@ struct queue_t {
struct queue_element_t *e;
};
-// Pushing information about a cell to be checked to our queue.
-static inline void
-push(struct queue_t *queue, const struct grid_t *grid, int id, int next)
-{
- assert(grid->size);
- queue->e[queue->tail].id = id;
- queue->e[queue->tail].next = next;
- grid->marked[id]++;
- queue->tail++;
-}
+static void push(struct queue_t *queue, const struct grid_t *grid, const
+ int id, const int next);
+
static void
checkfield(struct queue_t *q, const struct grid_t *g)
{
int cursor = HEAD(q).id;
- int nextval = HEAD(q).next;
// Write the amount of steps from the goal to this cell.
- g->path[cursor] = nextval;
+ g->path[cursor] = HEAD(q).next;
// Check if the cell is a walkable area, return if it isn't.
- switch(g->ar[cursor])
- {
- case 0: case 255: break;
- case 1: g->path[cursor] = -1; return; break;
- default: return;
+ if (unlikely((g->ar[cursor] != 0) && (g->ar[cursor] != 255))) {
+ if (g->ar[cursor] == 1)
+ g->path[cursor] = -1;
+ return;
}
// Check the cell to the right.
- if ( (cursor+1) % g->w != 0 &&
- (cursor+1) < g->size &&
- g->marked[cursor+1] == 0)
- push(q,g,cursor+1,nextval+1);
+ if (g->marked[cursor+1] == 0 &&
+ (cursor+1) % g->w != 0 &&
+ (cursor+1) < g->size )
+ push(q, g, cursor+1, HEAD(q).next + 1);
// Check the cell to the left.
- if ( (cursor) % g->w != 0 &&
- (cursor-1) >= 0 &&
- g->marked[cursor-1] == 0)
- push(q,g,cursor-1,nextval+1);
+ if (g->marked[cursor-1] == 0 &&
+ (cursor) % g->w != 0 &&
+ (cursor-1) >= 0)
+ push(q, g, cursor-1, HEAD(q).next + 1);
// Check the cell below.
- if ( (cursor + g->w) < g->size && g->marked[cursor + g->w] == 0 )
- push(q,g,cursor + g->w, nextval+1);
+ if (g->marked[cursor + g->w] == 0 &&
+ (cursor + g->w) < g->size)
+ push(q, g, cursor + g->w, HEAD(q).next + 1);
// Check the cell above.
- if ( (cursor - g->w) >= 0 && g->marked[cursor - g->w] == 0)
- push(q,g,cursor - g->w, nextval+1);
+ if (g->marked[cursor - g->w] == 0 &&
+ (cursor - g->w) >= 0)
+ push(q, g, cursor - g->w, HEAD(q).next + 1);
+}
+
+// Pushing information about a cell to be checked to our queue.
+static void
+push(struct queue_t *queue,
+ const struct grid_t *grid,
+ const int id,
+ const int next)
+{
+ queue->e[queue->tail].id = id;
+ queue->e[queue->tail].next = next;
+ grid->marked[id]++;
+ queue->tail++;
+}
+
+static void
+reset_grid_path(const struct grid_t *g)
+{
+ memset(g->path, '\0', g->size * sizeof(int));
+ memset(g->marked, '\0', g->size * sizeof(int));
}
/*
* Parse the grid input and allocate a matching memory segment
*
* XXX: Cheapo-error handling
+ * XXX: Now that reset_grid exists, calloc is redundant.
*/
-static struct grid_t *parse_grid(void) {
+static struct grid_t *
+parse_grid(void)
+{
struct grid_t *grid;
int ret,i;
grid = malloc(sizeof(struct grid_t));
assert(grid);
printf("How large is your grid (WxH)? ");
- scanf("%dx%d",&grid->w, &grid->h);
-
+ ret = scanf("%dx%d",&grid->w, &grid->h);
+ assert(ret == 2);
assert (grid->w > 0 && grid->h > 0);
grid->size = grid->w * grid->h;
@@ -104,21 +123,15 @@ static struct grid_t *parse_grid(void) {
ret = scanf("%d", &(grid->ar[i]));
assert (ret != 0);
}
+ reset_grid_path(grid);
return grid;
}
/*
- * Reset grid
- */
-static void reset_grid_path(struct grid_t *g) {
- memset(g->path, '\0', g->size * sizeof(int));
- memset(g->marked, '\0', g->size * sizeof(int));
-}
-
-/*
* Free grid
*/
-static void free_grid(struct grid_t *g)
+static void
+free_grid(struct grid_t *g)
{
free(g->ar);
free(g->path);
@@ -127,48 +140,45 @@ static void free_grid(struct grid_t *g)
}
/*
+ * Reset the queue, as if it was empty.
+ */
+static void
+reset_queue(struct queue_t *q)
+{
+ q->tail = 0;
+ q->head = 0;
+ q->e[0].id = 0;
+ q->e[0].next = 0;
+}
+
+/*
* Allocate and initialize the queue.
*/
-static struct queue_t *alloc_queue(const struct grid_t *grid)
+static struct queue_t *
+alloc_queue(const struct grid_t *grid)
{
struct queue_t *queue;
queue = calloc(1, sizeof(struct queue_t));
-
- queue->head = 0;
- queue->tail = 0;
-
queue->e = calloc(grid->size, sizeof(struct queue_element_t));
assert(queue->e);
+ reset_queue(queue);
return queue;
}
-/*
- * Reset the queue, as if it was empty.
- */
-static void reset_queue(struct queue_t *q, const struct grid_t *g)
-{
- struct queue_element_t *t = q->e;
- memset(q, '\0', sizeof(struct queue_t));
- q->e = t;
- memset(q->e, '\0', g->size);
-}
-
-/*
- * Free the queue.
- */
-static void free_queue(struct queue_t *q)
+static void
+free_queue(struct queue_t *q)
{
free(q->e);
free(q);
-};
+}
int main(void)
{
int i,o;
struct grid_t *grid;
struct queue_t *queue;
- struct timeval starttime, endtime;
+ struct timeval starttime, endtime, comptime;
grid = parse_grid();
queue = alloc_queue(grid);
@@ -178,17 +188,16 @@ int main(void)
for(o=0; o < RUNS; o++)
{
reset_grid_path(grid);
- reset_queue(queue, grid);
+ reset_queue(queue);
- for(i=0; i<grid->size; i++)
- {
+ for(i=0; i<grid->size; i++) {
if (grid->ar[i] == 255) {
push(queue, grid, i, 1);
}
}
// As long as there are unchecked cells in the queue, check the cells.
- while (grid->marked[HEAD(queue).id] ) {
+ while (likely(grid->marked[HEAD(queue).id] != 0)) {
checkfield(queue, grid);
queue->head++;
}
@@ -210,10 +219,11 @@ int main(void)
}
printf("\n\n");
- printf("Spent %d seconds and %d microseconds - avg. %.f usec per run\n",
- endtime.tv_sec - starttime.tv_sec,
- endtime.tv_usec - starttime.tv_usec,
- (float)(endtime.tv_usec - starttime.tv_usec) / (float) RUNS );
+ timersub(&endtime,&starttime,&comptime);
+ printf("Spent %lu seconds and %lu microseconds - avg. %.f usec per run\n",
+ comptime.tv_sec,
+ comptime.tv_usec,
+ (double)(((comptime.tv_sec*1000000) + comptime.tv_usec) / RUNS));
free_queue(queue);
free_grid(grid);

0 comments on commit 1682913

Please sign in to comment.