From 5553a48c5153381f053ad15c949e943d745e72f6 Mon Sep 17 00:00:00 2001 From: James Braun Date: Fri, 15 Mar 2024 00:15:53 -0500 Subject: [PATCH] Added mmap support for both color benchmark variants Change-Id: Idb4fc32d4691795bba623d579153459d79a1f2f6 --- src/gpu/pannotia/color/coloring_max.cpp | 281 ++++++++++++++++++--- src/gpu/pannotia/color/coloring_maxmin.cpp | 264 +++++++++++++++++-- 2 files changed, 488 insertions(+), 57 deletions(-) diff --git a/src/gpu/pannotia/color/coloring_max.cpp b/src/gpu/pannotia/color/coloring_max.cpp index b85245e50..79e5cc8ee 100644 --- a/src/gpu/pannotia/color/coloring_max.cpp +++ b/src/gpu/pannotia/color/coloring_max.cpp @@ -3,6 +3,7 @@ * Copyright © 2014 Advanced Micro Devices, Inc. * * Copyright (c) 2015 Mark D. Hill and David A. Wood * * Copyright (c) 2021 Gaurav Jain and Matthew D. Sinclair * + * Copyright (c) 2024 James Braun and Matthew D. Sinclair * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * @@ -64,6 +65,12 @@ #include "../graph_parser/parse.h" #include "../graph_parser/util.h" #include "kernel_max.h" +#include +#include +#include +#include +#include +#include #ifdef GEM5_FUSION #include @@ -76,20 +83,78 @@ void print_vector(int *vector, int num); int main(int argc, char **argv) { - char *tmpchar; + char *tmpchar = NULL; + bool mode_set = false; + bool create_mmap = false; + bool use_mmap = false; int num_nodes; int num_edges; int file_format = 1; bool directed = 0; + int opt; hipError_t err = hipSuccess; - if (argc == 3) { - tmpchar = argv[1]; //graph inputfile - file_format = atoi(argv[2]); //graph format - } else { - fprintf(stderr, "You did something wrong!\n"); + // Input arguments + while ((opt = getopt(argc, argv, "df:hm:t:")) != -1) { + switch (opt) { + case 'd': // Directed graph + directed = 1; + case 'f': // Input file name + tmpchar = optarg; + break; + case 'h': // Help + fprintf(stderr, "SWITCHES\n"); + fprintf(stderr, "\t-d\n"); + fprintf(stderr, "\t\tdirected graph (default is not directed)\n"); + fprintf(stderr, "\t-f [file name]\n"); + fprintf(stderr, "\t\tinput file name\n"); + fprintf(stderr, "\t-m [mode]\n"); + fprintf(stderr, "\t\toperation mode: default (run without mmap), generate, usemmap\n"); + fprintf(stderr, "\t-t [file type] \n"); + fprintf(stderr, "\t\tfile type (not required when running in usemmap mode): dimacs9 (0), metis (1), matrixmarket (2)\n"); + exit(0); + case 'm': // Mode + if (strcmp(optarg, "default") == 0 || optarg[0] == '0') { + mode_set = true; + } else if (strcmp(optarg, "generate") == 0 || optarg[0] == '1') { + create_mmap = true; + } else if (strcmp(optarg, "usemmap") == 0 || optarg[0] == '2') { + use_mmap = true; + } else { + fprintf(stderr, "Unrecognized mode: %s\n", optarg); + exit(1); + } + break; + case 't': // Input file type + if (strcmp(optarg, "dimacs9") == 0 || optarg[0] == '0') { + file_format = 0; + } else if (strcmp(optarg, "metis") == 0 || optarg[0] == '1') { + file_format = 1; + } else if (strcmp(optarg, "matrixmarket") == 0 || optarg[0] == '2') { + file_format = 2; + } else { + fprintf(stderr, "Unrecognized file type: %s\n", optarg); + exit(1); + } + break; + default: + fprintf(stderr, "Unrecognized switch: -%c\n", opt); + exit(1); + } + } + + if (!(mode_set || create_mmap || use_mmap)) { + fprintf(stderr, "Execution mode not specified! Use -h for help\n"); + exit(1); + } else if (use_mmap && (tmpchar != NULL || file_format != -1)) { + fprintf(stdout, "Ignoring input file specifiers\n"); + } else if ((mode_set || create_mmap) && tmpchar == NULL) { + fprintf(stderr, "Input file not specified! Use -h for help\n"); + exit(1); + } else if ((mode_set || create_mmap) && file_format == -1) { + fprintf(stderr, "Input file type not specified! Use -h for help\n"); exit(1); } @@ -97,29 +162,185 @@ int main(int argc, char **argv) // Allocate the CSR structure csr_array *csr; + int *node_value; + int *color; + + if (use_mmap) { + printf("Using an mmap!\n"); + + // get num_nodes + int fd = open("row_mmap.bin", std::ios::binary | std::fstream::in); + if (fd == -1) { + fprintf(stderr, "error: %s\n", strerror(errno)); + fprintf(stderr, "You need to create an mmapped input file! row_mmap.bin is missing!\n"); + exit(1); + } - // Parse graph file and store into a CSR format - if (file_format == 1) - csr = parseMetis(tmpchar, &num_nodes, &num_edges, directed); - else if (file_format == 0) - csr = parseCOO(tmpchar, &num_nodes, &num_edges, directed); - else { - printf("reserve for future"); - exit(1); - } + int offset = 0; + num_nodes = *((int *)mmap(NULL, 1 * sizeof(int), PROT_READ, MAP_PRIVATE, fd, offset)); + + // read row_array in + int *row_array_map = (int *)mmap(NULL, (num_nodes + 2) * sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); + + // Check that maping was sucessful + if (row_array_map == MAP_FAILED) { + fprintf(stderr, "row mmap failed!\n"); + exit(1); + } + + // Copy row_array + csr = (csr_array *)malloc(sizeof(csr_array)); + if (csr == NULL) { + printf("csr_array malloc failed!\n"); + exit(1); + } + + int *row_array = (int *)malloc((num_nodes + 1) * sizeof(int)); + memcpy(row_array, &row_array_map[1], (num_nodes + 1) * sizeof(int)); + + munmap(row_array_map, (num_nodes + 2) * sizeof(int)); + close(fd); + + // get num_edges + fd = open("col_mmap.bin", std::ios::binary | std::fstream::in); + if (fd == -1) { + fprintf(stderr, "error: %s\n", strerror(errno)); + fprintf(stderr, "You need to create an mmapped input file! col_mmap.bin is missing!\n"); + exit(1); + } + + offset = 0; + num_edges = *((int *)mmap(NULL, 1 * sizeof(int), PROT_READ, MAP_PRIVATE, fd, offset)); + + // read col_array in + int *col_array_map = (int *)mmap(NULL, (num_edges + 1) * sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); + + // Check that maping was sucessful + if (col_array_map == MAP_FAILED) { + fprintf(stderr, "col mmap failed!\n"); + exit(1); + } + + // Copy col_array + int *col_array = (int *)malloc(num_edges * sizeof(int)); + memcpy(col_array, &col_array_map[1], num_edges * sizeof(int)); + + munmap(col_array_map, (num_edges + 1) * sizeof(int)); + close(fd); + + memset(csr, 0, sizeof(csr_array)); + csr->row_array = row_array; + csr->col_array = col_array; + + // copy color and node_value arrays + fd = open("node_value.bin", std::ios::binary | std::fstream::in); + if (fd == -1) { + fprintf(stderr, "error: %s\n", strerror(errno)); + fprintf(stderr, "You need to create an mmapped input file! node_value.bin is missing!\n"); + exit(1); + } + + offset = 0; + int *node_value_map = (int *)mmap(NULL, num_nodes * sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); - // Allocate the vertex value array - int *node_value = (int *)malloc(num_nodes * sizeof(int)); - if (!node_value) fprintf(stderr, "node_value malloc failed\n"); - // Allocate the color array - int *color = (int *)malloc(num_nodes * sizeof(int)); - if (!color) fprintf(stderr, "color malloc failed\n"); - - // Initialize all the colors to -1 - // Randomize the value for each vertex - for (int i = 0; i < num_nodes; i++) { - color[i] = -1; - node_value[i] = rand() % RANGE; + // Check that maping was sucessful + if (node_value_map == MAP_FAILED) { + fprintf(stderr, "node_value mmap failed!\n"); + exit(1); + } + + // Allocate the vertex value array + node_value = (int *)malloc(num_nodes * sizeof(int)); + if (!node_value) fprintf(stderr, "node_value malloc failed\n"); + + memcpy(node_value, node_value_map, num_nodes * sizeof(int)); + munmap(node_value_map, num_nodes * sizeof(int)); + close(fd); + + fd = open("colors.bin", std::ios::binary | std::fstream::in); + if (fd == -1) { + fprintf(stderr, "error: %s\n", strerror(errno)); + fprintf(stderr, "You need to create an mmapped input file! colors.bin is missing!\n"); + exit(1); + } + + offset = 0; + int *colors_map = (int *)mmap(NULL, num_nodes * sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); + + // Check that maping was sucessful + if (colors_map == MAP_FAILED) { + fprintf(stderr, "colors mmap failed!\n"); + exit(1); + } + + // Allocate the color array + color = (int *)malloc(num_nodes * sizeof(int)); + if (!node_value) fprintf(stderr, "color malloc failed\n"); + + memcpy(color, colors_map, num_nodes * sizeof(int)); + munmap(colors_map, num_nodes * sizeof(int)); + close(fd); + } else { + // Parse graph file and store into a CSR format + if (file_format == 1) + csr = parseMetis(tmpchar, &num_nodes, &num_edges, directed); + else if (file_format == 0) + csr = parseCOO(tmpchar, &num_nodes, &num_edges, directed); + else { + printf("reserve for future"); + exit(1); + } + + // Allocate the vertex value array + node_value = (int *)malloc(num_nodes * sizeof(int)); + if (!node_value) fprintf(stderr, "node_value malloc failed\n"); + // Allocate the color array + color = (int *)malloc(num_nodes * sizeof(int)); + if (!color) fprintf(stderr, "color malloc failed\n"); + + // Initialize all the colors to -1 + // Randomize the value for each vertex + for (int i = 0; i < num_nodes; i++) { + color[i] = -1; + node_value[i] = rand() % RANGE; + } + + if (create_mmap) { + printf("creating an mmap\n"); + + // prints csr to file + std::ofstream row_out("row_mmap.bin", std::ios::binary); + + row_out.write((char *)&num_nodes, sizeof(int)); + row_out.write((char *)csr->row_array, (num_nodes + 1) * sizeof(int)); + + row_out.close(); + + // num_edges * sizeof(int) + std::ofstream col_out("col_mmap.bin", std::ios::binary); + + col_out.write((char *)&num_edges, sizeof(int)); + col_out.write((char *)csr->col_array, num_edges * sizeof(int)); + + col_out.close(); + + // prints color and node_value arrays + std::ofstream node_out("node_value.bin", std::ios::binary); + node_out.write((char *)node_value, num_nodes * sizeof(int)); + node_out.close(); + + std::ofstream color_out("colors.bin", std::ios::binary); + color_out.write((char *)color, num_nodes * sizeof(int)); + color_out.close(); + + free(node_value); + free(color); + + csr->freeArrays(); + free(csr); + printf("mmaps created!\n"); + return 0; + } } int *row_d; @@ -129,7 +350,7 @@ int main(int argc, char **argv) int *color_d; int *node_value_d; int *stop_d; - + // Create device-side buffers for the graph err = hipMalloc(&row_d, num_nodes * sizeof(int)); if (err != hipSuccess) { @@ -155,11 +376,13 @@ int main(int argc, char **argv) fprintf(stderr, "ERROR: hipMalloc color_d (size:%d) => %s\n", num_nodes , hipGetErrorString(err)); return -1; } + err = hipMalloc(&node_value_d, num_nodes * sizeof(int)); if (err != hipSuccess) { fprintf(stderr, "ERROR: hipMalloc node_value_d (size:%d) => %s\n", num_nodes , hipGetErrorString(err)); return -1; } + err = hipMalloc(&max_d, num_nodes * sizeof(int)); if (err != hipSuccess) { fprintf(stderr, "ERROR: hipMalloc max_d (size:%d) => %s\n", num_nodes , hipGetErrorString(err)); @@ -203,6 +426,7 @@ int main(int argc, char **argv) return -1; } + int block_size = 256; int num_blocks = (num_nodes + block_size - 1) / block_size; @@ -217,7 +441,6 @@ int main(int argc, char **argv) // double timer3 = gettime(); while (stop) { - stop = 0; // Copy the termination variable to the device diff --git a/src/gpu/pannotia/color/coloring_maxmin.cpp b/src/gpu/pannotia/color/coloring_maxmin.cpp index 7e7cd5121..10ca1c3df 100644 --- a/src/gpu/pannotia/color/coloring_maxmin.cpp +++ b/src/gpu/pannotia/color/coloring_maxmin.cpp @@ -3,6 +3,7 @@ * Copyright © 2014 Advanced Micro Devices, Inc. * * Copyright (c) 2015 Mark D. Hill and David A. Wood * * Copyright (c) 2021 Gaurav Jain and Matthew D. Sinclair * + * Copyright (c) 2024 James Braun and Matthew D. Sinclair * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * @@ -64,6 +65,12 @@ #include "../graph_parser/parse.h" #include "../graph_parser/util.h" #include "kernel_maxmin.h" +#include +#include +#include +#include +#include +#include #ifdef GEM5_FUSION #include @@ -76,50 +83,251 @@ void print_vector(int *vector, int num); int main(int argc, char **argv) { - char *tmpchar; + char *tmpchar = NULL; + bool mode_set = false; + bool create_mmap = false; + bool use_mmap = false; int num_nodes; int num_edges; int file_format = 1; bool directed = 0; + int opt; hipError_t err = hipSuccess; - if (argc == 3) { - tmpchar = argv[1]; //graph inputfile - file_format = atoi(argv[2]); //graph format - } else { - fprintf(stderr, "You did something wrong!\n"); - exit(1); + // Input arguments + while ((opt = getopt(argc, argv, "df:hm:t:")) != -1) { + switch (opt) { + case 'd': // Directed graph + directed = 1; + case 'f': // Input file name + tmpchar = optarg; + break; + case 'h': // Help + fprintf(stderr, "SWITCHES\n"); + fprintf(stderr, "\t-d\n"); + fprintf(stderr, "\t\tdirected graph (default is not directed)\n"); + fprintf(stderr, "\t-f [file name]\n"); + fprintf(stderr, "\t\tinput file name\n"); + fprintf(stderr, "\t-m [mode]\n"); + fprintf(stderr, "\t\toperation mode: default (run without mmap), generate, usemmap\n"); + fprintf(stderr, "\t-t [file type] \n"); + fprintf(stderr, "\t\tfile type (not required when running in usemmap mode): dimacs9 (0), metis (1), matrixmarket (2)\n"); + exit(0); + case 'm': // Mode + if (strcmp(optarg, "default") == 0 || optarg[0] == '0') { + mode_set = true; + } else if (strcmp(optarg, "generate") == 0 || optarg[0] == '1') { + create_mmap = true; + } else if (strcmp(optarg, "usemmap") == 0 || optarg[0] == '2') { + use_mmap = true; + } else { + fprintf(stderr, "Unrecognized mode: %s\n", optarg); + exit(1); + } + break; + case 't': // Input file type + if (strcmp(optarg, "dimacs9") == 0 || optarg[0] == '0') { + file_format = 0; + } else if (strcmp(optarg, "metis") == 0 || optarg[0] == '1') { + file_format = 1; + } else if (strcmp(optarg, "matrixmarket") == 0 || optarg[0] == '2') { + file_format = 2; + } else { + fprintf(stderr, "Unrecognized file type: %s\n", optarg); + exit(1); + } + break; + default: + fprintf(stderr, "Unrecognized switch: -%c\n", opt); + exit(1); + } } srand(7); // Allocate the CSR structure csr_array *csr; + int *node_value; + int *color; + + if (use_mmap) { + printf("Using an mmap!\n"); + + // get num_nodes + int fd = open("row_mmap.bin", std::ios::binary | std::fstream::in); + if (fd == -1) { + fprintf(stderr, "error: %s\n", strerror(errno)); + fprintf(stderr, "You need to create an mmapped input file!\n"); + exit(1); + } - // Parse graph file and store into a CSR format - if (file_format == 1) - csr = parseMetis(tmpchar, &num_nodes, &num_edges, directed); - else if (file_format == 0) - csr = parseCOO(tmpchar, &num_nodes, &num_edges, directed); - else { - printf("reserve for future"); - exit(1); - } + int offset = 0; + num_nodes = *((int *)mmap(NULL, 1 * sizeof(int), PROT_READ, MAP_PRIVATE, fd, offset)); + + // read row_array in + int *row_array_map = (int *)mmap(NULL, (num_nodes + 2) * sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); + + // Check that maping was sucessful + if (row_array_map == MAP_FAILED) { + fprintf(stderr, "mmap failed!\n"); + exit(1); + } + + // Copy row_array + csr = (csr_array *)malloc(sizeof(csr_array)); + if (csr == NULL) { + printf("csr_array malloc failed!\n"); + exit(1); + } + + int *row_array = (int *)malloc((num_nodes + 1) * sizeof(int)); + memcpy(row_array, &row_array_map[1], (num_nodes + 1) * sizeof(int)); + + munmap(row_array_map, (num_nodes + 2) * sizeof(int)); + close(fd); + + // get num_edges + fd = open("col_mmap.bin", std::ios::binary | std::fstream::in); + if (fd == -1) { + fprintf(stderr, "error: %s\n", strerror(errno)); + fprintf(stderr, "You need to create an mmapped input file!\n"); + exit(1); + } + + offset = 0; + num_edges = *((int *)mmap(NULL, 1 * sizeof(int), PROT_READ, MAP_PRIVATE, fd, offset)); + + // read col_array in + int *col_array_map = (int *)mmap(NULL, (num_edges + 1) * sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); + + // Check that maping was sucessful + if (col_array_map == MAP_FAILED) { + fprintf(stderr, "mmap failed!\n"); + exit(1); + } + + // Copy col_array + int *col_array = (int *)malloc(num_edges * sizeof(int)); + memcpy(col_array, &col_array_map[1], num_edges * sizeof(int)); + + munmap(col_array_map, (num_edges + 1) * sizeof(int)); + close(fd); + + memset(csr, 0, sizeof(csr_array)); + csr->row_array = row_array; + csr->col_array = col_array; + + // copy color and node_value arrays + fd = open("node_value.bin", std::ios::binary | std::fstream::in); + if (fd == -1) { + fprintf(stderr, "error: %s\n", strerror(errno)); + fprintf(stderr, "You need to create an mmapped input file! node_value.bin is missing!\n"); + exit(1); + } + + offset = 0; + int *node_value_map = (int *)mmap(NULL, num_nodes * sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); + + // Check that maping was sucessful + if (node_value_map == MAP_FAILED) { + fprintf(stderr, "node_value mmap failed!\n"); + exit(1); + } - // Allocate the vertex value array - int *node_value = (int *)malloc(num_nodes * sizeof(int)); - if (!node_value) fprintf(stderr, "node_value malloc failed\n"); - // Allocate the color array - int *color = (int *)malloc(num_nodes * sizeof(int)); - if (!color) fprintf(stderr, "color malloc failed\n"); - - // Initialize all the colors to -1 - // Randomize the value for each vertex - for (int i = 0; i < num_nodes; i++) { - color[i] = -1; - node_value[i] = rand() % RANGE; + // Allocate the vertex value array + node_value = (int *)malloc(num_nodes * sizeof(int)); + if (!node_value) fprintf(stderr, "node_value malloc failed\n"); + + memcpy(node_value, node_value_map, num_nodes * sizeof(int)); + munmap(node_value_map, num_nodes * sizeof(int)); + close(fd); + + fd = open("colors.bin", std::ios::binary | std::fstream::in); + if (fd == -1) { + fprintf(stderr, "error: %s\n", strerror(errno)); + fprintf(stderr, "You need to create an mmapped input file! colors.bin is missing!\n"); + exit(1); + } + + offset = 0; + int *colors_map = (int *)mmap(NULL, num_nodes * sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); + + // Check that maping was sucessful + if (colors_map == MAP_FAILED) { + fprintf(stderr, "colors mmap failed!\n"); + exit(1); + } + + // Allocate the color array + color = (int *)malloc(num_nodes * sizeof(int)); + if (!node_value) fprintf(stderr, "color malloc failed\n"); + + memcpy(color, colors_map, num_nodes * sizeof(int)); + munmap(colors_map, num_nodes * sizeof(int)); + close(fd); + } else { + // Parse graph file and store into a CSR format + if (file_format == 1) + csr = parseMetis(tmpchar, &num_nodes, &num_edges, directed); + else if (file_format == 0) + csr = parseCOO(tmpchar, &num_nodes, &num_edges, directed); + else { + printf("reserve for future"); + exit(1); + } + + // Allocate the vertex value array + node_value = (int *)malloc(num_nodes * sizeof(int)); + if (!node_value) fprintf(stderr, "node_value malloc failed\n"); + // Allocate the color array + color = (int *)malloc(num_nodes * sizeof(int)); + if (!color) fprintf(stderr, "color malloc failed\n"); + + // Initialize all the colors to -1 + // Randomize the value for each vertex + for (int i = 0; i < num_nodes; i++) { + color[i] = -1; + node_value[i] = rand() % RANGE; + } + + if (create_mmap) { + printf("creating an mmap\n"); + + // prints csr to file + std::ofstream row_out("row_mmap.bin", std::ios::binary); + + row_out.write((char *)&num_nodes, sizeof(int)); + row_out.write((char *)csr->row_array, (num_nodes + 1) * sizeof(int)); + + row_out.close(); + + // num_edges * sizeof(int) + std::ofstream col_out("col_mmap.bin", std::ios::binary); + + col_out.write((char *)&num_edges, sizeof(int)); + col_out.write((char *)csr->col_array, num_edges * sizeof(int)); + + col_out.close(); + + // prints color and node_value arrays + std::ofstream node_out("node_value.bin", std::ios::binary); + node_out.write((char *)node_value, num_nodes * sizeof(int)); + node_out.close(); + + std::ofstream color_out("colors.bin", std::ios::binary); + color_out.write((char *)color, num_nodes * sizeof(int)); + color_out.close(); + + free(node_value); + free(color); + + csr->freeArrays(); + free(csr); + printf("mmaps created!\n"); + return 0; + } } int *row_d;