added XSBench
This commit is contained in:
@@ -1,20 +1,116 @@
|
||||
add_compile_options(-g -O3 -DNDEBUG -gdwarf-3)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(mimalloc-bench CXX C)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
function(add_coz_run_target name)
|
||||
set(one_value_args "")
|
||||
set(multi_value_args COMMAND)
|
||||
set(options "")
|
||||
cmake_parse_arguments(COZ_RUN "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "No build type selected, default to *** Release ***")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
add_custom_target(${name}
|
||||
COMMENT "Running coz for ${name}"
|
||||
COMMAND ${PROJECT_SOURCE_DIR}/coz run --- ${COZ_RUN_COMMAND}
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS coz)
|
||||
endfunction()
|
||||
FUNCTION(PREPEND var prefix)
|
||||
SET(listVar "")
|
||||
FOREACH(f ${ARGN})
|
||||
LIST(APPEND listVar "${prefix}/${f}")
|
||||
ENDFOREACH(f)
|
||||
SET(${var} "${listVar}" PARENT_SCOPE)
|
||||
ENDFUNCTION(PREPEND)
|
||||
|
||||
file(GLOB cmake_files */CMakeLists.txt)
|
||||
foreach(filepath ${cmake_files})
|
||||
get_filename_component(dir ${filepath} DIRECTORY)
|
||||
add_subdirectory(${dir})
|
||||
endforeach(filepath)
|
||||
set(cfrac_sources
|
||||
cfrac.c
|
||||
pops.c pconst.c pio.c
|
||||
pabs.c pneg.c pcmp.c podd.c phalf.c
|
||||
padd.c psub.c pmul.c pdivmod.c psqrt.c ppowmod.c
|
||||
atop.c ptoa.c itop.c utop.c ptou.c errorp.c
|
||||
pfloat.c pidiv.c pimod.c picmp.c
|
||||
primes.c pcfrac.c pgcd.c)
|
||||
PREPEND(cfrac_sources cfrac/ ${cfrac_sources})
|
||||
|
||||
set(espresso_sources
|
||||
cofactor.c cols.c compl.c contain.c cubestr.c cvrin.c cvrm.c cvrmisc.c cvrout.c
|
||||
dominate.c equiv.c espresso.c essen.c exact.c expand.c gasp.c getopt.c gimpel.c
|
||||
globals.c hack.c indep.c irred.c main.c map.c matrix.c mincov.c opo.c pair.c part.c
|
||||
primes.c reduce.c rows.c set.c setc.c sharp.c sminterf.c solution.c sparse.c unate.c
|
||||
utility.c verify.c)
|
||||
PREPEND(espresso_sources espresso/ ${espresso_sources})
|
||||
|
||||
set(barnes_sources
|
||||
code.c code_io.c load.c grav.c getparam.c util.c)
|
||||
PREPEND(barnes_sources barnes/ ${barnes_sources})
|
||||
|
||||
# turn off warnings..
|
||||
message(STATUS "${CMAKE_C_COMPILER_ID}")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
|
||||
set(FLAGS " -w -Wno-implicit-function-declaration -Wno-implicit-int -Wno-int-conversion -Wno-return-mismatch -Wno-incompatible-pointer-types -mabi=purecap-benchmark")
|
||||
string(APPEND CMAKE_C_FLAGS ${FLAGS})
|
||||
string(APPEND CMAKE_CXX_FLAGS ${FLAGS})
|
||||
endif()
|
||||
|
||||
add_executable(cfrac ${cfrac_sources})
|
||||
target_compile_options(cfrac PRIVATE $<$<C_COMPILER_ID:GNU>:-std=gnu89>)
|
||||
target_compile_definitions(cfrac PRIVATE NOMEMOPT=1)
|
||||
target_link_libraries(cfrac m)
|
||||
|
||||
add_executable(espresso ${espresso_sources})
|
||||
target_compile_options(espresso PRIVATE $<$<C_COMPILER_ID:GNU>:-std=gnu89>)
|
||||
target_link_libraries(espresso m)
|
||||
|
||||
# add_executable(barnes ${barnes_sources})
|
||||
# target_link_libraries(barnes m)
|
||||
|
||||
# add_executable(larson larson/larson.cpp)
|
||||
# target_compile_options(larson PRIVATE -Wno-unused-result)
|
||||
# target_compile_definitions(larson PRIVATE CPP=1)
|
||||
# target_link_libraries(larson pthread)
|
||||
|
||||
# add_executable(larson-sized larson/larson.cpp)
|
||||
# target_compile_options(larson-sized PRIVATE -Wno-unused-result -fsized-deallocation)
|
||||
# target_compile_definitions(larson-sized PRIVATE CPP=1 SIZED=1)
|
||||
# target_link_libraries(larson-sized pthread)
|
||||
|
||||
# add_executable(alloc-test alloc-test/test_common.cpp alloc-test/allocator_tester.cpp)
|
||||
# target_compile_definitions(alloc-test PRIVATE BENCH=4)
|
||||
# target_link_libraries(alloc-test pthread)
|
||||
|
||||
# if(NOT APPLE)
|
||||
# add_executable(sh6bench shbench/sh6bench-new.c)
|
||||
# target_compile_definitions(sh6bench PRIVATE BENCH=1 SYS_MULTI_THREAD=1)
|
||||
# target_link_libraries(sh6bench pthread)
|
||||
|
||||
# add_executable(sh8bench shbench/sh8bench-new.c)
|
||||
# target_compile_definitions(sh8bench PRIVATE BENCH=1 SYS_MULTI_THREAD=1)
|
||||
# target_link_libraries(sh8bench pthread)
|
||||
# endif()
|
||||
|
||||
# add_executable(cache-scratch cache-scratch/cache-scratch.cpp)
|
||||
# target_link_libraries(cache-scratch pthread)
|
||||
|
||||
# add_executable(cache-thrash cache-thrash/cache-thrash.cpp)
|
||||
# target_link_libraries(cache-thrash pthread)
|
||||
|
||||
add_executable(xmalloc-test xmalloc-test/xmalloc-test.c)
|
||||
target_link_libraries(xmalloc-test pthread)
|
||||
|
||||
# add_executable(malloc-large-old malloc-large/malloc-large-old.cpp)
|
||||
# target_link_libraries(malloc-large-old pthread)
|
||||
|
||||
# add_executable(malloc-large malloc-large/malloc-large.cpp)
|
||||
# target_link_libraries(malloc-large pthread)
|
||||
|
||||
# add_executable(mstress mstress/mstress.c)
|
||||
# target_link_libraries(mstress pthread)
|
||||
|
||||
# add_executable(mleak mleak/mleak.c)
|
||||
# target_link_libraries(mleak pthread)
|
||||
|
||||
# add_executable(rptest rptest/rptest.c rptest/thread.c rptest/timer.c)
|
||||
# target_compile_options(rptest PRIVATE -fpermissive)
|
||||
# target_include_directories(rptest PRIVATE rptest)
|
||||
# target_link_libraries(rptest pthread m)
|
||||
|
||||
# add_executable(glibc-simple glibc-bench/bench-malloc-simple.c)
|
||||
# target_link_libraries(glibc-simple pthread)
|
||||
|
||||
# add_executable(glibc-thread glibc-bench/bench-malloc-thread.c)
|
||||
# target_link_libraries(glibc-thread pthread)
|
||||
|
||||
#
|
||||
@@ -24,8 +24,8 @@
|
||||
#include <sys/resource.h>
|
||||
#include "malloc.h"
|
||||
|
||||
#define malloc MALLOCCHERI
|
||||
#define free FREECHERI
|
||||
// #define malloc MALLOCCHERI
|
||||
// #define free FREECHERI
|
||||
|
||||
// #include "bench-timing.h"
|
||||
// #include "json-lib.h"
|
||||
@@ -197,7 +197,7 @@ static void usage (const char *name)
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
INITREGULARALLOC();
|
||||
//INITREGULARALLOC();
|
||||
long size = 16;
|
||||
if (argc == 2)
|
||||
size = strtol (argv[1], NULL, 0);
|
||||
@@ -205,9 +205,12 @@ main (int argc, char **argv)
|
||||
if (argc > 2 || size <= 0)
|
||||
usage (argv[0]);
|
||||
|
||||
bench (size);
|
||||
// bench (size);
|
||||
bench (2*size);
|
||||
bench (4*size);
|
||||
//bench (4*size);
|
||||
//bench (8*size);
|
||||
// bench (16*size);
|
||||
// bench (32*size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
sh build.sh
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o glibc-cheri.stat ./glibc-bench.out
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o glibc-regular-2.stat ./glibc-bench.out
|
||||
@@ -2,8 +2,8 @@
|
||||
#include <stdlib.h>
|
||||
#include "malloc.h"
|
||||
|
||||
#define malloc MALLOCCHERI
|
||||
#define free FREECHERI
|
||||
// #define malloc MALLOCCHERI
|
||||
// #define free FREECHERI
|
||||
|
||||
// performing various sizes of mallocs are free
|
||||
void
|
||||
@@ -22,21 +22,25 @@ bench (unsigned long n) {
|
||||
for (i = 0; i < n; i++){
|
||||
ptr[i] = 1;
|
||||
}
|
||||
printf("Sleep 10 seconds......\n");
|
||||
sleep(10);
|
||||
printf("Free memory.\n");
|
||||
// printf("Sleep 10 seconds......\n");
|
||||
// sleep(10);
|
||||
// printf("Free memory.\n");
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
int main(){
|
||||
|
||||
INITREGULARALLOC();
|
||||
bench(8);
|
||||
bench(30);
|
||||
// INITREGULARALLOC();
|
||||
// bench(8);
|
||||
// bench(30);
|
||||
// bench(100);
|
||||
// bench(600);
|
||||
// Run one by one
|
||||
bench(10);
|
||||
bench(100);
|
||||
bench(600);
|
||||
bench(1000);
|
||||
bench(7000);
|
||||
bench(10000);
|
||||
bench(100000);
|
||||
|
||||
// int *ptr;
|
||||
// unsigned long i,n;
|
||||
|
||||
@@ -20,8 +20,8 @@ All rights reserved.
|
||||
|
||||
#include "malloc.h"
|
||||
|
||||
#define malloc MALLOCCHERI
|
||||
#define free FREECHERI
|
||||
// #define malloc MALLOCCHERI
|
||||
// #define free FREECHERI
|
||||
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ void * walk(void *param)
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
INITREGULARALLOC();
|
||||
// INITREGULARALLOC();
|
||||
#ifdef DEBUG
|
||||
printf("DEBUG:sizeof(struct l)=%ld\n",sizeof(struct l));
|
||||
#endif
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
sh build.sh
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o memaccesstest-cheri.stat ./memaccesstest.out
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o memaccesstest.stat ./memaccesstest.out
|
||||
@@ -1,2 +1,2 @@
|
||||
sh build.sh
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o loadmem-cheri.stats ./loadmem.out
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o loadmem-regular.stat ./loadmem.out
|
||||
230
benchmarks/benchmarks/XSbench/GridInit.c
Normal file
230
benchmarks/benchmarks/XSbench/GridInit.c
Normal file
@@ -0,0 +1,230 @@
|
||||
#include "XSbench_header.h"
|
||||
|
||||
SimulationData grid_init_do_not_profile( Inputs in, int mype )
|
||||
{
|
||||
// Structure to hold all allocated simuluation data arrays
|
||||
SimulationData SD;
|
||||
|
||||
// Keep track of how much data we're allocating
|
||||
size_t nbytes = 0;
|
||||
|
||||
// Set the initial seed value
|
||||
uint64_t seed = 42;
|
||||
|
||||
// loop variable
|
||||
long e = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize Nuclide Grids
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
if(mype == 0) printf("Intializing nuclide grids...\n");
|
||||
|
||||
// First, we need to initialize our nuclide grid. This comes in the form
|
||||
// of a flattened 2D array that hold all the information we need to define
|
||||
// the cross sections for all isotopes in the simulation.
|
||||
// The grid is composed of "NuclideGridPoint" structures, which hold the
|
||||
// energy level of the grid point and all associated XS data at that level.
|
||||
// An array of structures (AOS) is used instead of
|
||||
// a structure of arrays, as the grid points themselves are accessed in
|
||||
// a random order, but all cross section interaction channels and the
|
||||
// energy level are read whenever the gridpoint is accessed, meaning the
|
||||
// AOS is more cache efficient.
|
||||
|
||||
// Initialize Nuclide Grid
|
||||
SD.length_nuclide_grid = in.n_isotopes * in.n_gridpoints;
|
||||
SD.nuclide_grid = (NuclideGridPoint *) malloc( SD.length_nuclide_grid * sizeof(NuclideGridPoint));
|
||||
assert(SD.nuclide_grid != NULL);
|
||||
nbytes += SD.length_nuclide_grid * sizeof(NuclideGridPoint);
|
||||
for( int i = 0; i < SD.length_nuclide_grid; i++ )
|
||||
{
|
||||
SD.nuclide_grid[i].energy = LCG_random_double(&seed);
|
||||
SD.nuclide_grid[i].total_xs = LCG_random_double(&seed);
|
||||
SD.nuclide_grid[i].elastic_xs = LCG_random_double(&seed);
|
||||
SD.nuclide_grid[i].absorbtion_xs = LCG_random_double(&seed);
|
||||
SD.nuclide_grid[i].fission_xs = LCG_random_double(&seed);
|
||||
SD.nuclide_grid[i].nu_fission_xs = LCG_random_double(&seed);
|
||||
}
|
||||
|
||||
// Sort so that each nuclide has data stored in ascending energy order.
|
||||
for( int i = 0; i < in.n_isotopes; i++ )
|
||||
qsort( &SD.nuclide_grid[i*in.n_gridpoints], in.n_gridpoints, sizeof(NuclideGridPoint), NGP_compare);
|
||||
|
||||
// error debug check
|
||||
/*
|
||||
for( int i = 0; i < in.n_isotopes; i++ )
|
||||
{
|
||||
printf("NUCLIDE %d ==============================\n", i);
|
||||
for( int j = 0; j < in.n_gridpoints; j++ )
|
||||
printf("E%d = %lf\n", j, SD.nuclide_grid[i * in.n_gridpoints + j].energy);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize Acceleration Structure
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
if( in.grid_type == NUCLIDE )
|
||||
{
|
||||
SD.length_unionized_energy_array = 0;
|
||||
SD.length_index_grid = 0;
|
||||
}
|
||||
|
||||
if( in.grid_type == UNIONIZED )
|
||||
{
|
||||
if(mype == 0) printf("Intializing unionized grid...\n");
|
||||
|
||||
// Allocate space to hold the union of all nuclide energy data
|
||||
SD.length_unionized_energy_array = in.n_isotopes * in.n_gridpoints;
|
||||
SD.unionized_energy_array = (double *) malloc( SD.length_unionized_energy_array * sizeof(double));
|
||||
assert(SD.unionized_energy_array != NULL );
|
||||
nbytes += SD.length_unionized_energy_array * sizeof(double);
|
||||
|
||||
// Copy energy data over from the nuclide energy grid
|
||||
for( int i = 0; i < SD.length_unionized_energy_array; i++ )
|
||||
SD.unionized_energy_array[i] = SD.nuclide_grid[i].energy;
|
||||
|
||||
// Sort unionized energy array
|
||||
qsort( SD.unionized_energy_array, SD.length_unionized_energy_array, sizeof(double), double_compare);
|
||||
|
||||
// Allocate space to hold the acceleration grid indices
|
||||
SD.length_index_grid = SD.length_unionized_energy_array * in.n_isotopes;
|
||||
SD.index_grid = (int *) malloc( SD.length_index_grid * sizeof(int));
|
||||
assert(SD.index_grid != NULL);
|
||||
nbytes += SD.length_index_grid * sizeof(int);
|
||||
|
||||
// Generates the double indexing grid
|
||||
int * idx_low = (int *) calloc( in.n_isotopes, sizeof(int));
|
||||
assert(idx_low != NULL );
|
||||
double * energy_high = (double *) malloc( in.n_isotopes * sizeof(double));
|
||||
assert(energy_high != NULL );
|
||||
|
||||
for( int i = 0; i < in.n_isotopes; i++ )
|
||||
energy_high[i] = SD.nuclide_grid[i * in.n_gridpoints + 1].energy;
|
||||
|
||||
for( long e = 0; e < SD.length_unionized_energy_array; e++ )
|
||||
{
|
||||
double unionized_energy = SD.unionized_energy_array[e];
|
||||
for( long i = 0; i < in.n_isotopes; i++ )
|
||||
{
|
||||
if( unionized_energy < energy_high[i] )
|
||||
SD.index_grid[e * in.n_isotopes + i] = idx_low[i];
|
||||
else if( idx_low[i] == in.n_gridpoints - 2 )
|
||||
SD.index_grid[e * in.n_isotopes + i] = idx_low[i];
|
||||
else
|
||||
{
|
||||
idx_low[i]++;
|
||||
SD.index_grid[e * in.n_isotopes + i] = idx_low[i];
|
||||
energy_high[i] = SD.nuclide_grid[i * in.n_gridpoints + idx_low[i] + 1].energy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(idx_low);
|
||||
free(energy_high);
|
||||
}
|
||||
|
||||
if( in.grid_type == HASH )
|
||||
{
|
||||
if(mype == 0) printf("Intializing hash grid...\n");
|
||||
SD.length_unionized_energy_array = 0;
|
||||
SD.length_index_grid = in.hash_bins * in.n_isotopes;
|
||||
SD.index_grid = (int *) malloc( SD.length_index_grid * sizeof(int));
|
||||
assert(SD.index_grid != NULL);
|
||||
nbytes += SD.length_index_grid * sizeof(int);
|
||||
|
||||
double du = 1.0 / in.hash_bins;
|
||||
|
||||
// For each energy level in the hash table
|
||||
#pragma omp parallel for
|
||||
for( e = 0; e < in.hash_bins; e++ )
|
||||
{
|
||||
double energy = e * du;
|
||||
|
||||
// We need to determine the bounding energy levels for all isotopes
|
||||
for( long i = 0; i < in.n_isotopes; i++ )
|
||||
{
|
||||
SD.index_grid[e * in.n_isotopes + i] = grid_search_nuclide( in.n_gridpoints, energy, SD.nuclide_grid + i * in.n_gridpoints, 0, in.n_gridpoints-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize Materials and Concentrations
|
||||
////////////////////////////////////////////////////////////////////
|
||||
if(mype == 0) printf("Intializing material data...\n");
|
||||
|
||||
// Set the number of nuclides in each material
|
||||
SD.num_nucs = load_num_nucs(in.n_isotopes);
|
||||
SD.length_num_nucs = 12; // There are always 12 materials in XSBench
|
||||
|
||||
// Intialize the flattened 2D grid of material data. The grid holds
|
||||
// a list of nuclide indices for each of the 12 material types. The
|
||||
// grid is allocated as a full square grid, even though not all
|
||||
// materials have the same number of nuclides.
|
||||
SD.mats = load_mats(SD.num_nucs, in.n_isotopes, &SD.max_num_nucs);
|
||||
SD.length_mats = SD.length_num_nucs * SD.max_num_nucs;
|
||||
|
||||
// Intialize the flattened 2D grid of nuclide concentration data. The grid holds
|
||||
// a list of nuclide concentrations for each of the 12 material types. The
|
||||
// grid is allocated as a full square grid, even though not all
|
||||
// materials have the same number of nuclides.
|
||||
SD.concs = load_concs(SD.num_nucs, SD.max_num_nucs);
|
||||
SD.length_concs = SD.length_mats;
|
||||
|
||||
// Allocate and initialize replicas
|
||||
#ifdef AML
|
||||
// num_nucs
|
||||
aml_replicaset_hwloc_create(&(SD.num_nucs_replica),
|
||||
SD.length_num_nucs * sizeof(*(SD.num_nucs)),
|
||||
HWLOC_OBJ_CORE,
|
||||
HWLOC_DISTANCES_KIND_FROM_OS |
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
|
||||
nbytes += (SD.num_nucs_replica)->n * (SD.num_nucs_replica)->size;
|
||||
aml_replicaset_init(SD.num_nucs_replica, SD.num_nucs);
|
||||
|
||||
// concs
|
||||
aml_replicaset_hwloc_create(&(SD.concs_replica),
|
||||
SD.length_concs * sizeof(*(SD.concs)),
|
||||
HWLOC_OBJ_CORE,
|
||||
HWLOC_DISTANCES_KIND_FROM_OS |
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
|
||||
nbytes += (SD.concs_replica)->n * (SD.concs_replica)->size;
|
||||
aml_replicaset_init(SD.concs_replica, SD.concs);
|
||||
|
||||
// unionized_energy_array
|
||||
if( in.grid_type == UNIONIZED ){
|
||||
aml_replicaset_hwloc_create(&(SD.unionized_energy_array_replica),
|
||||
SD.length_unionized_energy_array * sizeof(*(SD.unionized_energy_array)),
|
||||
HWLOC_OBJ_CORE,
|
||||
HWLOC_DISTANCES_KIND_FROM_OS |
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
|
||||
nbytes += (SD.unionized_energy_array_replica)->n * (SD.unionized_energy_array_replica)->size;
|
||||
aml_replicaset_init(SD.unionized_energy_array_replica, SD.unionized_energy_array);
|
||||
}
|
||||
|
||||
// index grid
|
||||
if( in.grid_type == UNIONIZED || in.grid_type == HASH ){
|
||||
aml_replicaset_hwloc_create(&(SD.index_grid_replica),
|
||||
SD.length_index_grid * sizeof(*(SD.index_grid)),
|
||||
HWLOC_OBJ_CORE,
|
||||
HWLOC_DISTANCES_KIND_FROM_OS |
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
|
||||
nbytes += (SD.index_grid_replica)->n * (SD.index_grid_replica)->size;
|
||||
aml_replicaset_init(SD.index_grid_replica, SD.index_grid);
|
||||
}
|
||||
|
||||
// nuclide grid
|
||||
aml_replicaset_hwloc_create(&(SD.nuclide_grid_replica),
|
||||
SD.length_nuclide_grid * sizeof(*(SD.nuclide_grid)),
|
||||
HWLOC_OBJ_CORE,
|
||||
HWLOC_DISTANCES_KIND_FROM_OS |
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
|
||||
nbytes += (SD.nuclide_grid_replica)->n * (SD.nuclide_grid_replica)->size;
|
||||
aml_replicaset_init(SD.nuclide_grid_replica, SD.nuclide_grid);
|
||||
#endif
|
||||
|
||||
if(mype == 0) printf("Intialization complete. Allocated %.0lf MB of data.\n", nbytes/1024.0/1024.0 );
|
||||
return SD;
|
||||
}
|
||||
BIN
benchmarks/benchmarks/XSbench/GridInit.o
Normal file
BIN
benchmarks/benchmarks/XSbench/GridInit.o
Normal file
Binary file not shown.
123
benchmarks/benchmarks/XSbench/Main.c
Normal file
123
benchmarks/benchmarks/XSbench/Main.c
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "XSbench_header.h"
|
||||
|
||||
#ifdef MPI
|
||||
#include<mpi.h>
|
||||
#endif
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
// =====================================================================
|
||||
// Initialization & Command Line Read-In
|
||||
// =====================================================================
|
||||
int version = 20;
|
||||
int mype = 0;
|
||||
double omp_start, omp_end;
|
||||
int nprocs = 1;
|
||||
unsigned long long verification;
|
||||
|
||||
#ifdef MPI
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &mype);
|
||||
#endif
|
||||
|
||||
#ifdef AML
|
||||
aml_init(&argc, &argv);
|
||||
#endif
|
||||
|
||||
// Process CLI Fields -- store in "Inputs" structure
|
||||
Inputs in = read_CLI( argc, argv );
|
||||
|
||||
// Set number of OpenMP Threads
|
||||
#ifdef OPENMP
|
||||
omp_set_num_threads(in.nthreads);
|
||||
#endif
|
||||
|
||||
// Print-out of Input Summary
|
||||
if( mype == 0 )
|
||||
print_inputs( in, nprocs, version );
|
||||
|
||||
// =====================================================================
|
||||
// Prepare Nuclide Energy Grids, Unionized Energy Grid, & Material Data
|
||||
// This is not reflective of a real Monte Carlo simulation workload,
|
||||
// therefore, do not profile this region!
|
||||
// =====================================================================
|
||||
|
||||
SimulationData SD;
|
||||
|
||||
// If read from file mode is selected, skip initialization and load
|
||||
// all simulation data structures from file instead
|
||||
if( in.binary_mode == READ )
|
||||
SD = binary_read(in);
|
||||
else
|
||||
SD = grid_init_do_not_profile( in, mype );
|
||||
|
||||
// If writing from file mode is selected, write all simulation data
|
||||
// structures to file
|
||||
if( in.binary_mode == WRITE && mype == 0 )
|
||||
binary_write(in, SD);
|
||||
|
||||
|
||||
// =====================================================================
|
||||
// Cross Section (XS) Parallel Lookup Simulation
|
||||
// This is the section that should be profiled, as it reflects a
|
||||
// realistic continuous energy Monte Carlo macroscopic cross section
|
||||
// lookup kernel.
|
||||
// =====================================================================
|
||||
|
||||
if( mype == 0 )
|
||||
{
|
||||
printf("\n");
|
||||
border_print();
|
||||
center_print("SIMULATION", 79);
|
||||
border_print();
|
||||
}
|
||||
|
||||
// Start Simulation Timer
|
||||
omp_start = get_time();
|
||||
|
||||
// Run simulation
|
||||
if( in.simulation_method == EVENT_BASED )
|
||||
{
|
||||
if( in.kernel_id == 0 )
|
||||
verification = run_event_based_simulation(in, SD, mype);
|
||||
else if( in.kernel_id == 1 )
|
||||
verification = run_event_based_simulation_optimization_1(in, SD, mype);
|
||||
else
|
||||
{
|
||||
printf("Error: No kernel ID %d found!\n", in.kernel_id);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
verification = run_history_based_simulation(in, SD, mype);
|
||||
|
||||
if( mype == 0)
|
||||
{
|
||||
printf("\n" );
|
||||
printf("Simulation complete.\n" );
|
||||
}
|
||||
|
||||
// End Simulation Timer
|
||||
omp_end = get_time();
|
||||
|
||||
// =====================================================================
|
||||
// Output Results & Finalize
|
||||
// =====================================================================
|
||||
|
||||
// Final Hash Step
|
||||
verification = verification % 999983;
|
||||
|
||||
// Print / Save Results and Exit
|
||||
int is_invalid_result = print_results( in, mype, omp_end-omp_start, nprocs, verification );
|
||||
|
||||
#ifdef MPI
|
||||
MPI_Finalize();
|
||||
#endif
|
||||
|
||||
#ifdef AML
|
||||
aml_finalize();
|
||||
#endif
|
||||
|
||||
return is_invalid_result;
|
||||
}
|
||||
BIN
benchmarks/benchmarks/XSbench/Main.o
Normal file
BIN
benchmarks/benchmarks/XSbench/Main.o
Normal file
Binary file not shown.
86
benchmarks/benchmarks/XSbench/Makefile
Normal file
86
benchmarks/benchmarks/XSbench/Makefile
Normal file
@@ -0,0 +1,86 @@
|
||||
#===============================================================================
|
||||
# User Options
|
||||
#===============================================================================
|
||||
|
||||
# Compiler can be set below, or via environment variable
|
||||
CC = cc
|
||||
OPTIMIZE = yes
|
||||
OPENMP = no
|
||||
DEBUG = yes
|
||||
PROFILE = no
|
||||
MPI = no
|
||||
AML = no
|
||||
|
||||
#===============================================================================
|
||||
# Program name & source code list
|
||||
#===============================================================================
|
||||
|
||||
program = XSBench
|
||||
|
||||
source = \
|
||||
Main.c \
|
||||
io.c \
|
||||
Simulations.c \
|
||||
GridInit.c \
|
||||
XSutils.c \
|
||||
Materials.c
|
||||
|
||||
obj = $(source:.c=.o)
|
||||
|
||||
#===============================================================================
|
||||
# Sets Flags
|
||||
#===============================================================================
|
||||
|
||||
# Standard Flags
|
||||
|
||||
# Linker Flags
|
||||
LDFLAGS = -lm
|
||||
|
||||
# LLVM Compiler
|
||||
# ifneq (,$(findstring clang,$(CC)))
|
||||
# CFLAGS += -flto
|
||||
# ifeq ($(OPENMP),yes)
|
||||
# CFLAGS += -fopenmp -DOPENMP
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# # Intel Compiler
|
||||
# ifneq (,$(findstring intel,$(CC)))
|
||||
# CFLAGS += -ipo
|
||||
# ifeq ($(OPENMP),yes)
|
||||
# CFLAGS += -fopenmp -DOPENMP
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# # Debug Flags
|
||||
# ifeq ($(DEBUG),yes)
|
||||
# CFLAGS += -g
|
||||
# LDFLAGS += -g
|
||||
# endif
|
||||
|
||||
# Profiling Flags
|
||||
|
||||
# Optimization Flags
|
||||
|
||||
# AML
|
||||
|
||||
CFLAGS += -g -Wall -mabi=purecap-benchmark -lpthread
|
||||
|
||||
#===============================================================================
|
||||
# Targets to Build
|
||||
#===============================================================================
|
||||
|
||||
$(program): $(obj) XSbench_header.h Makefile
|
||||
$(CC) $(CFLAGS) $(obj) -o $@ $(LDFLAGS)
|
||||
|
||||
%.o: %.c XSbench_header.h Makefile
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(program) $(obj)
|
||||
|
||||
edit:
|
||||
vim -p $(source) XSbench_header.h
|
||||
|
||||
run:
|
||||
./$(program)
|
||||
117
benchmarks/benchmarks/XSbench/Materials.c
Normal file
117
benchmarks/benchmarks/XSbench/Materials.c
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
// Material data is hard coded into the functions in this file.
|
||||
// Note that there are 12 materials present in H-M (large or small)
|
||||
|
||||
#include "XSbench_header.h"
|
||||
|
||||
// num_nucs represents the number of nuclides that each material contains
|
||||
int * load_num_nucs(long n_isotopes)
|
||||
{
|
||||
int * num_nucs = (int*)malloc(12*sizeof(int));
|
||||
|
||||
// Material 0 is a special case (fuel). The H-M small reactor uses
|
||||
// 34 nuclides, while H-M larges uses 300.
|
||||
if( n_isotopes == 68 )
|
||||
num_nucs[0] = 34; // HM Small is 34, H-M Large is 321
|
||||
else
|
||||
num_nucs[0] = 321; // HM Small is 34, H-M Large is 321
|
||||
|
||||
num_nucs[1] = 5;
|
||||
num_nucs[2] = 4;
|
||||
num_nucs[3] = 4;
|
||||
num_nucs[4] = 27;
|
||||
num_nucs[5] = 21;
|
||||
num_nucs[6] = 21;
|
||||
num_nucs[7] = 21;
|
||||
num_nucs[8] = 21;
|
||||
num_nucs[9] = 21;
|
||||
num_nucs[10] = 9;
|
||||
num_nucs[11] = 9;
|
||||
|
||||
return num_nucs;
|
||||
}
|
||||
|
||||
// Assigns an array of nuclide ID's to each material
|
||||
int * load_mats( int * num_nucs, long n_isotopes, int * max_num_nucs )
|
||||
{
|
||||
*max_num_nucs = 0;
|
||||
int num_mats = 12;
|
||||
for( int m = 0; m < num_mats; m++ )
|
||||
{
|
||||
if( num_nucs[m] > *max_num_nucs )
|
||||
*max_num_nucs = num_nucs[m];
|
||||
}
|
||||
int * mats = (int *) malloc( num_mats * (*max_num_nucs) * sizeof(int) );
|
||||
|
||||
// Small H-M has 34 fuel nuclides
|
||||
int mats0_Sml[] = { 58, 59, 60, 61, 40, 42, 43, 44, 45, 46, 1, 2, 3, 7,
|
||||
8, 9, 10, 29, 57, 47, 48, 0, 62, 15, 33, 34, 52, 53,
|
||||
54, 55, 56, 18, 23, 41 }; //fuel
|
||||
// Large H-M has 300 fuel nuclides
|
||||
int mats0_Lrg[321] = { 58, 59, 60, 61, 40, 42, 43, 44, 45, 46, 1, 2, 3, 7,
|
||||
8, 9, 10, 29, 57, 47, 48, 0, 62, 15, 33, 34, 52, 53,
|
||||
54, 55, 56, 18, 23, 41 }; //fuel
|
||||
for( int i = 0; i < 321-34; i++ )
|
||||
mats0_Lrg[34+i] = 68 + i; // H-M large adds nuclides to fuel only
|
||||
|
||||
// These are the non-fuel materials
|
||||
int mats1[] = { 63, 64, 65, 66, 67 }; // cladding
|
||||
int mats2[] = { 24, 41, 4, 5 }; // cold borated water
|
||||
int mats3[] = { 24, 41, 4, 5 }; // hot borated water
|
||||
int mats4[] = { 19, 20, 21, 22, 35, 36, 37, 38, 39, 25, 27, 28, 29,
|
||||
30, 31, 32, 26, 49, 50, 51, 11, 12, 13, 14, 6, 16,
|
||||
17 }; // RPV
|
||||
int mats5[] = { 24, 41, 4, 5, 19, 20, 21, 22, 35, 36, 37, 38, 39, 25,
|
||||
49, 50, 51, 11, 12, 13, 14 }; // lower radial reflector
|
||||
int mats6[] = { 24, 41, 4, 5, 19, 20, 21, 22, 35, 36, 37, 38, 39, 25,
|
||||
49, 50, 51, 11, 12, 13, 14 }; // top reflector / plate
|
||||
int mats7[] = { 24, 41, 4, 5, 19, 20, 21, 22, 35, 36, 37, 38, 39, 25,
|
||||
49, 50, 51, 11, 12, 13, 14 }; // bottom plate
|
||||
int mats8[] = { 24, 41, 4, 5, 19, 20, 21, 22, 35, 36, 37, 38, 39, 25,
|
||||
49, 50, 51, 11, 12, 13, 14 }; // bottom nozzle
|
||||
int mats9[] = { 24, 41, 4, 5, 19, 20, 21, 22, 35, 36, 37, 38, 39, 25,
|
||||
49, 50, 51, 11, 12, 13, 14 }; // top nozzle
|
||||
int mats10[] = { 24, 41, 4, 5, 63, 64, 65, 66, 67 }; // top of FA's
|
||||
int mats11[] = { 24, 41, 4, 5, 63, 64, 65, 66, 67 }; // bottom FA's
|
||||
|
||||
// H-M large v small dependency
|
||||
if( n_isotopes == 68 )
|
||||
memcpy( mats, mats0_Sml, num_nucs[0] * sizeof(int) );
|
||||
else
|
||||
memcpy( mats, mats0_Lrg, num_nucs[0] * sizeof(int) );
|
||||
|
||||
// Copy other materials
|
||||
memcpy( mats + *max_num_nucs * 1, mats1, num_nucs[1] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 2, mats2, num_nucs[2] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 3, mats3, num_nucs[3] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 4, mats4, num_nucs[4] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 5, mats5, num_nucs[5] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 6, mats6, num_nucs[6] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 7, mats7, num_nucs[7] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 8, mats8, num_nucs[8] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 9, mats9, num_nucs[9] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 10, mats10, num_nucs[10] * sizeof(int) );
|
||||
memcpy( mats + *max_num_nucs * 11, mats11, num_nucs[11] * sizeof(int) );
|
||||
|
||||
return mats;
|
||||
}
|
||||
|
||||
// Randomizes the concentrations of all nuclides in a variety of materials
|
||||
double * load_concs( int * num_nucs, int max_num_nucs )
|
||||
{
|
||||
uint64_t seed = STARTING_SEED * STARTING_SEED;
|
||||
double * concs = (double *) malloc( 12 * max_num_nucs * sizeof( double ) );
|
||||
|
||||
for( int i = 0; i < 12; i++ )
|
||||
for( int j = 0; j < num_nucs[i]; j++ )
|
||||
concs[i * max_num_nucs + j] = LCG_random_double(&seed);
|
||||
|
||||
// test
|
||||
/*
|
||||
for( int i = 0; i < 12; i++ )
|
||||
for( int j = 0; j < num_nucs[i]; j++ )
|
||||
printf("concs[%d][%d] = %lf\n", i, j, concs[i][j] );
|
||||
*/
|
||||
|
||||
return concs;
|
||||
}
|
||||
BIN
benchmarks/benchmarks/XSbench/Materials.o
Normal file
BIN
benchmarks/benchmarks/XSbench/Materials.o
Normal file
Binary file not shown.
871
benchmarks/benchmarks/XSbench/Simulations.c
Normal file
871
benchmarks/benchmarks/XSbench/Simulations.c
Normal file
@@ -0,0 +1,871 @@
|
||||
#include "XSbench_header.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// BASELINE FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// All "baseline" code is at the top of this file. The baseline code is a simple
|
||||
// implementation of the algorithm, with only minor CPU optimizations in place.
|
||||
// Following these functions are a number of optimized variants,
|
||||
// which each deploy a different combination of optimizations strategies. By
|
||||
// default, XSBench will only run the baseline implementation. Optimized variants
|
||||
// must be specifically selected using the "-k <optimized variant ID>" command
|
||||
// line argument.
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned long long run_event_based_simulation(Inputs in, SimulationData SD, int mype)
|
||||
{
|
||||
if( mype == 0)
|
||||
printf("Beginning event based simulation...\n");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SUMMARY: Simulation Data Structure Manifest for "SD" Object
|
||||
// Here we list all heap arrays (and lengths) in SD that would need to be
|
||||
// offloaded manually if using an accelerator with a seperate memory space
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// int * num_nucs; // Length = length_num_nucs;
|
||||
// double * concs; // Length = length_concs
|
||||
// int * mats; // Length = length_mats
|
||||
// double * unionized_energy_array; // Length = length_unionized_energy_array
|
||||
// int * index_grid; // Length = length_index_grid
|
||||
// NuclideGridPoint * nuclide_grid; // Length = length_nuclide_grid
|
||||
//
|
||||
// Note: "unionized_energy_array" and "index_grid" can be of zero length
|
||||
// depending on lookup method.
|
||||
//
|
||||
// Note: "Lengths" are given as the number of objects in the array, not the
|
||||
// number of bytes.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin Actual Simulation Loop
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned long long verification = 0;
|
||||
int i = 0;
|
||||
#pragma omp parallel for schedule(dynamic,100) reduction(+:verification)
|
||||
for( i = 0; i < in.lookups; i++ )
|
||||
{
|
||||
#ifdef AML
|
||||
int * num_nucs = aml_replicaset_hwloc_local_replica(SD.num_nucs_replica);
|
||||
double * concs = aml_replicaset_hwloc_local_replica(SD.concs_replica);
|
||||
double * unionized_energy_array = aml_replicaset_hwloc_local_replica(SD.unionized_energy_array_replica);
|
||||
int * index_grid = aml_replicaset_hwloc_local_replica(SD.index_grid_replica);
|
||||
NuclideGridPoint * nuclide_grid = aml_replicaset_hwloc_local_replica(SD.nuclide_grid_replica);
|
||||
#else
|
||||
int * num_nucs = SD.num_nucs;
|
||||
double * concs = SD.concs;
|
||||
double * unionized_energy_array = SD.unionized_energy_array;
|
||||
int * index_grid = SD.index_grid;
|
||||
NuclideGridPoint * nuclide_grid = SD.nuclide_grid;
|
||||
#endif
|
||||
|
||||
// Set the initial seed value
|
||||
uint64_t seed = STARTING_SEED;
|
||||
|
||||
// Forward seed to lookup index (we need 2 samples per lookup)
|
||||
seed = fast_forward_LCG(seed, 2*i);
|
||||
|
||||
// Randomly pick an energy and material for the particle
|
||||
double p_energy = LCG_random_double(&seed);
|
||||
int mat = pick_mat(&seed);
|
||||
|
||||
double macro_xs_vector[5] = {0};
|
||||
|
||||
// Perform macroscopic Cross Section Lookup
|
||||
calculate_macro_xs(
|
||||
p_energy, // Sampled neutron energy (in lethargy)
|
||||
mat, // Sampled material type index neutron is in
|
||||
in.n_isotopes, // Total number of isotopes in simulation
|
||||
in.n_gridpoints, // Number of gridpoints per isotope in simulation
|
||||
num_nucs, // 1-D array with number of nuclides per material
|
||||
concs, // Flattened 2-D array with concentration of each nuclide in each material
|
||||
unionized_energy_array, // 1-D Unionized energy array
|
||||
index_grid, // Flattened 2-D grid holding indices into nuclide grid for each unionized energy level
|
||||
nuclide_grid, // Flattened 2-D grid holding energy levels and XS_data for all nuclides in simulation
|
||||
SD.mats, // Flattened 2-D array with nuclide indices defining composition of each type of material
|
||||
macro_xs_vector, // 1-D array with result of the macroscopic cross section (5 different reaction channels)
|
||||
in.grid_type, // Lookup type (nuclide, hash, or unionized)
|
||||
in.hash_bins, // Number of hash bins used (if using hash lookup type)
|
||||
SD.max_num_nucs // Maximum number of nuclides present in any material
|
||||
);
|
||||
|
||||
// For verification, and to prevent the compiler from optimizing
|
||||
// all work out, we interrogate the returned macro_xs_vector array
|
||||
// to find its maximum value index, then increment the verification
|
||||
// value by that index. In this implementation, we prevent thread
|
||||
// contention by using an OMP reduction on the verification value.
|
||||
// For accelerators, a different approach might be required
|
||||
// (e.g., atomics, reduction of thread-specific values in large
|
||||
// array via CUDA thrust, etc).
|
||||
double max = -1.0;
|
||||
int max_idx = 0;
|
||||
for(int j = 0; j < 5; j++ )
|
||||
{
|
||||
if( macro_xs_vector[j] > max )
|
||||
{
|
||||
max = macro_xs_vector[j];
|
||||
max_idx = j;
|
||||
}
|
||||
}
|
||||
verification += max_idx+1;
|
||||
}
|
||||
|
||||
return verification;
|
||||
}
|
||||
|
||||
unsigned long long run_history_based_simulation(Inputs in, SimulationData SD, int mype)
|
||||
{
|
||||
if( mype == 0)
|
||||
printf("Beginning history based simulation...\n");
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SUMMARY: Simulation Data Structure Manifest for "SD" Object
|
||||
// Here we list all heap arrays (and lengths) in SD that would need to be
|
||||
// offloaded manually if using an accelerator with a seperate memory space
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// int * num_nucs; // Length = length_num_nucs;
|
||||
// double * concs; // Length = length_concs
|
||||
// int * mats; // Length = length_mats
|
||||
// double * unionized_energy_array; // Length = length_unionized_energy_array
|
||||
// int * index_grid; // Length = length_index_grid
|
||||
// NuclideGridPoint * nuclide_grid; // Length = length_nuclide_grid
|
||||
//
|
||||
// Note: "unionized_energy_array" and "index_grid" can be of zero length
|
||||
// depending on lookup method.
|
||||
//
|
||||
// Note: "Lengths" are given as the number of objects in the array, not the
|
||||
// number of bytes.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned long long verification = 0;
|
||||
|
||||
// Begin outer lookup loop over particles. This loop is independent.
|
||||
int p = 0;
|
||||
#pragma omp parallel for schedule(dynamic, 100) reduction(+:verification)
|
||||
for( p = 0; p < in.particles; p++ )
|
||||
{
|
||||
#ifdef AML
|
||||
int * num_nucs = aml_replicaset_hwloc_local_replica(SD.num_nucs_replica);
|
||||
double * concs = aml_replicaset_hwloc_local_replica(SD.concs_replica);
|
||||
double * unionized_energy_array = aml_replicaset_hwloc_local_replica(SD.unionized_energy_array_replica);
|
||||
int * index_grid = aml_replicaset_hwloc_local_replica(SD.index_grid_replica);
|
||||
NuclideGridPoint * nuclide_grid = aml_replicaset_hwloc_local_replica(SD.nuclide_grid_replica);
|
||||
#else
|
||||
int * num_nucs = SD.num_nucs;
|
||||
double * concs = SD.concs;
|
||||
double * unionized_energy_array = SD.unionized_energy_array;
|
||||
int * index_grid = SD.index_grid;
|
||||
NuclideGridPoint * nuclide_grid = SD.nuclide_grid;
|
||||
#endif
|
||||
|
||||
// Set the initial seed value
|
||||
uint64_t seed = STARTING_SEED;
|
||||
|
||||
// Forward seed to lookup index (we need 2 samples per lookup, and
|
||||
// we may fast forward up to 5 times after each lookup)
|
||||
seed = fast_forward_LCG(seed, p*in.lookups*2*5);
|
||||
|
||||
// Randomly pick an energy and material for the particle
|
||||
double p_energy = LCG_random_double(&seed);
|
||||
int mat = pick_mat(&seed);
|
||||
|
||||
// Inner XS Lookup Loop
|
||||
// This loop is dependent!
|
||||
// i.e., Next iteration uses data computed in previous iter.
|
||||
for( int i = 0; i < in.lookups; i++ )
|
||||
{
|
||||
double macro_xs_vector[5] = {0};
|
||||
|
||||
// Perform macroscopic Cross Section Lookup
|
||||
calculate_macro_xs(
|
||||
p_energy, // Sampled neutron energy (in lethargy)
|
||||
mat, // Sampled material type neutron is in
|
||||
in.n_isotopes, // Total number of isotopes in simulation
|
||||
in.n_gridpoints, // Number of gridpoints per isotope in simulation
|
||||
num_nucs, // 1-D array with number of nuclides per material
|
||||
concs, // Flattened 2-D array with concentration of each nuclide in each material
|
||||
unionized_energy_array, // 1-D Unionized energy array
|
||||
index_grid, // Flattened 2-D grid holding indices into nuclide grid for each unionized energy level
|
||||
nuclide_grid, // Flattened 2-D grid holding energy levels and XS_data for all nuclides in simulation
|
||||
SD.mats, // Flattened 2-D array with nuclide indices for each type of material
|
||||
macro_xs_vector, // 1-D array with result of the macroscopic cross section (5 different reaction channels)
|
||||
in.grid_type, // Lookup type (nuclide, hash, or unionized)
|
||||
in.hash_bins, // Number of hash bins used (if using hash lookups)
|
||||
SD.max_num_nucs // Maximum number of nuclides present in any material
|
||||
);
|
||||
|
||||
|
||||
// For verification, and to prevent the compiler from optimizing
|
||||
// all work out, we interrogate the returned macro_xs_vector array
|
||||
// to find its maximum value index, then increment the verification
|
||||
// value by that index. In this implementation, we prevent thread
|
||||
// contention by using an OMP reduction on it. For other accelerators,
|
||||
// a different approach might be required (e.g., atomics, reduction
|
||||
// of thread-specific values in large array via CUDA thrust, etc)
|
||||
double max = -1.0;
|
||||
int max_idx = 0;
|
||||
for(int j = 0; j < 5; j++ )
|
||||
{
|
||||
if( macro_xs_vector[j] > max )
|
||||
{
|
||||
max = macro_xs_vector[j];
|
||||
max_idx = j;
|
||||
}
|
||||
}
|
||||
verification += max_idx+1;
|
||||
|
||||
// Randomly pick next energy and material for the particle
|
||||
// Also incorporates results from macro_xs lookup to
|
||||
// enforce loop dependency.
|
||||
// In a real MC app, this dependency is expressed in terms
|
||||
// of branching physics sampling, whereas here we are just
|
||||
// artificially enforcing this dependence based on fast
|
||||
// forwarding the LCG state
|
||||
uint64_t n_forward = 0;
|
||||
for( int j = 0; j < 5; j++ )
|
||||
if( macro_xs_vector[j] > 1.0 )
|
||||
n_forward++;
|
||||
if( n_forward > 0 )
|
||||
seed = fast_forward_LCG(seed, n_forward);
|
||||
|
||||
p_energy = LCG_random_double(&seed);
|
||||
mat = pick_mat(&seed);
|
||||
}
|
||||
|
||||
}
|
||||
return verification;
|
||||
}
|
||||
|
||||
// Calculates the microscopic cross section for a given nuclide & energy
|
||||
void calculate_micro_xs( double p_energy, int nuc, long n_isotopes,
|
||||
long n_gridpoints,
|
||||
double * restrict egrid, int * restrict index_data,
|
||||
NuclideGridPoint * restrict nuclide_grids,
|
||||
long idx, double * restrict xs_vector, int grid_type, int hash_bins ){
|
||||
// Variables
|
||||
double f;
|
||||
NuclideGridPoint * low, * high;
|
||||
|
||||
// If using only the nuclide grid, we must perform a binary search
|
||||
// to find the energy location in this particular nuclide's grid.
|
||||
if( grid_type == NUCLIDE )
|
||||
{
|
||||
// Perform binary search on the Nuclide Grid to find the index
|
||||
idx = grid_search_nuclide( n_gridpoints, p_energy, &nuclide_grids[nuc*n_gridpoints], 0, n_gridpoints-1);
|
||||
|
||||
// pull ptr from nuclide grid and check to ensure that
|
||||
// we're not reading off the end of the nuclide's grid
|
||||
if( idx == n_gridpoints - 1 )
|
||||
low = &nuclide_grids[nuc*n_gridpoints + idx - 1];
|
||||
else
|
||||
low = &nuclide_grids[nuc*n_gridpoints + idx];
|
||||
}
|
||||
else if( grid_type == UNIONIZED) // Unionized Energy Grid - we already know the index, no binary search needed.
|
||||
{
|
||||
// pull ptr from energy grid and check to ensure that
|
||||
// we're not reading off the end of the nuclide's grid
|
||||
if( index_data[idx * n_isotopes + nuc] == n_gridpoints - 1 )
|
||||
low = &nuclide_grids[nuc*n_gridpoints + index_data[idx * n_isotopes + nuc] - 1];
|
||||
else
|
||||
low = &nuclide_grids[nuc*n_gridpoints + index_data[idx * n_isotopes + nuc]];
|
||||
}
|
||||
else // Hash grid
|
||||
{
|
||||
// load lower bounding index
|
||||
int u_low = index_data[idx * n_isotopes + nuc];
|
||||
|
||||
// Determine higher bounding index
|
||||
int u_high;
|
||||
if( idx == hash_bins - 1 )
|
||||
u_high = n_gridpoints - 1;
|
||||
else
|
||||
u_high = index_data[(idx+1)*n_isotopes + nuc] + 1;
|
||||
|
||||
// Check edge cases to make sure energy is actually between these
|
||||
// Then, if things look good, search for gridpoint in the nuclide grid
|
||||
// within the lower and higher limits we've calculated.
|
||||
double e_low = nuclide_grids[nuc*n_gridpoints + u_low].energy;
|
||||
double e_high = nuclide_grids[nuc*n_gridpoints + u_high].energy;
|
||||
int lower;
|
||||
if( p_energy <= e_low )
|
||||
lower = 0;
|
||||
else if( p_energy >= e_high )
|
||||
lower = n_gridpoints - 1;
|
||||
else
|
||||
lower = grid_search_nuclide( n_gridpoints, p_energy, &nuclide_grids[nuc*n_gridpoints], u_low, u_high);
|
||||
|
||||
if( lower == n_gridpoints - 1 )
|
||||
low = &nuclide_grids[nuc*n_gridpoints + lower - 1];
|
||||
else
|
||||
low = &nuclide_grids[nuc*n_gridpoints + lower];
|
||||
}
|
||||
|
||||
high = low + 1;
|
||||
|
||||
// calculate the re-useable interpolation factor
|
||||
f = (high->energy - p_energy) / (high->energy - low->energy);
|
||||
|
||||
// Total XS
|
||||
xs_vector[0] = high->total_xs - f * (high->total_xs - low->total_xs);
|
||||
|
||||
// Elastic XS
|
||||
xs_vector[1] = high->elastic_xs - f * (high->elastic_xs - low->elastic_xs);
|
||||
|
||||
// Absorbtion XS
|
||||
xs_vector[2] = high->absorbtion_xs - f * (high->absorbtion_xs - low->absorbtion_xs);
|
||||
|
||||
// Fission XS
|
||||
xs_vector[3] = high->fission_xs - f * (high->fission_xs - low->fission_xs);
|
||||
|
||||
// Nu Fission XS
|
||||
xs_vector[4] = high->nu_fission_xs - f * (high->nu_fission_xs - low->nu_fission_xs);
|
||||
}
|
||||
|
||||
// Calculates macroscopic cross section based on a given material & energy
|
||||
void calculate_macro_xs( double p_energy, int mat, long n_isotopes,
|
||||
long n_gridpoints, int * restrict num_nucs,
|
||||
double * restrict concs,
|
||||
double * restrict egrid, int * restrict index_data,
|
||||
NuclideGridPoint * restrict nuclide_grids,
|
||||
int * restrict mats,
|
||||
double * restrict macro_xs_vector, int grid_type, int hash_bins, int max_num_nucs ){
|
||||
int p_nuc; // the nuclide we are looking up
|
||||
long idx = -1;
|
||||
double conc; // the concentration of the nuclide in the material
|
||||
|
||||
// cleans out macro_xs_vector
|
||||
for( int k = 0; k < 5; k++ )
|
||||
macro_xs_vector[k] = 0;
|
||||
|
||||
// If we are using the unionized energy grid (UEG), we only
|
||||
// need to perform 1 binary search per macroscopic lookup.
|
||||
// If we are using the nuclide grid search, it will have to be
|
||||
// done inside of the "calculate_micro_xs" function for each different
|
||||
// nuclide in the material.
|
||||
if( grid_type == UNIONIZED )
|
||||
idx = grid_search( n_isotopes * n_gridpoints, p_energy, egrid);
|
||||
else if( grid_type == HASH )
|
||||
{
|
||||
double du = 1.0 / hash_bins;
|
||||
idx = p_energy / du;
|
||||
}
|
||||
|
||||
// Once we find the pointer array on the UEG, we can pull the data
|
||||
// from the respective nuclide grids, as well as the nuclide
|
||||
// concentration data for the material
|
||||
// Each nuclide from the material needs to have its micro-XS array
|
||||
// looked up & interpolatied (via calculate_micro_xs). Then, the
|
||||
// micro XS is multiplied by the concentration of that nuclide
|
||||
// in the material, and added to the total macro XS array.
|
||||
// (Independent -- though if parallelizing, must use atomic operations
|
||||
// or otherwise control access to the xs_vector and macro_xs_vector to
|
||||
// avoid simulataneous writing to the same data structure)
|
||||
for( int j = 0; j < num_nucs[mat]; j++ )
|
||||
{
|
||||
double xs_vector[5];
|
||||
p_nuc = mats[mat*max_num_nucs + j];
|
||||
conc = concs[mat*max_num_nucs + j];
|
||||
calculate_micro_xs( p_energy, p_nuc, n_isotopes,
|
||||
n_gridpoints, egrid, index_data,
|
||||
nuclide_grids, idx, xs_vector, grid_type, hash_bins );
|
||||
for( int k = 0; k < 5; k++ )
|
||||
macro_xs_vector[k] += xs_vector[k] * conc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// binary search for energy on unionized energy grid
|
||||
// returns lower index
|
||||
long grid_search( long n, double quarry, double * restrict A)
|
||||
{
|
||||
long lowerLimit = 0;
|
||||
long upperLimit = n-1;
|
||||
long examinationPoint;
|
||||
long length = upperLimit - lowerLimit;
|
||||
|
||||
while( length > 1 )
|
||||
{
|
||||
examinationPoint = lowerLimit + ( length / 2 );
|
||||
|
||||
if( A[examinationPoint] > quarry )
|
||||
upperLimit = examinationPoint;
|
||||
else
|
||||
lowerLimit = examinationPoint;
|
||||
|
||||
length = upperLimit - lowerLimit;
|
||||
}
|
||||
|
||||
return lowerLimit;
|
||||
}
|
||||
|
||||
// binary search for energy on nuclide energy grid
|
||||
long grid_search_nuclide( long n, double quarry, NuclideGridPoint * A, long low, long high)
|
||||
{
|
||||
long lowerLimit = low;
|
||||
long upperLimit = high;
|
||||
long examinationPoint;
|
||||
long length = upperLimit - lowerLimit;
|
||||
|
||||
while( length > 1 )
|
||||
{
|
||||
examinationPoint = lowerLimit + ( length / 2 );
|
||||
|
||||
if( A[examinationPoint].energy > quarry )
|
||||
upperLimit = examinationPoint;
|
||||
else
|
||||
lowerLimit = examinationPoint;
|
||||
|
||||
length = upperLimit - lowerLimit;
|
||||
}
|
||||
|
||||
return lowerLimit;
|
||||
}
|
||||
|
||||
// picks a material based on a probabilistic distribution
|
||||
int pick_mat( uint64_t * seed )
|
||||
{
|
||||
// I have a nice spreadsheet supporting these numbers. They are
|
||||
// the fractions (by volume) of material in the core. Not a
|
||||
// *perfect* approximation of where XS lookups are going to occur,
|
||||
// but this will do a good job of biasing the system nonetheless.
|
||||
|
||||
double dist[12];
|
||||
dist[0] = 0.140; // fuel
|
||||
dist[1] = 0.052; // cladding
|
||||
dist[2] = 0.275; // cold, borated water
|
||||
dist[3] = 0.134; // hot, borated water
|
||||
dist[4] = 0.154; // RPV
|
||||
dist[5] = 0.064; // Lower, radial reflector
|
||||
dist[6] = 0.066; // Upper reflector / top plate
|
||||
dist[7] = 0.055; // bottom plate
|
||||
dist[8] = 0.008; // bottom nozzle
|
||||
dist[9] = 0.015; // top nozzle
|
||||
dist[10] = 0.025; // top of fuel assemblies
|
||||
dist[11] = 0.013; // bottom of fuel assemblies
|
||||
|
||||
double roll = LCG_random_double(seed);
|
||||
|
||||
// makes a pick based on the distro
|
||||
for( int i = 0; i < 12; i++ )
|
||||
{
|
||||
double running = 0;
|
||||
for( int j = i; j > 0; j-- )
|
||||
running += dist[j];
|
||||
if( roll < running )
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double LCG_random_double(uint64_t * seed)
|
||||
{
|
||||
// LCG parameters
|
||||
const uint64_t m = 9223372036854775808ULL; // 2^63
|
||||
const uint64_t a = 2806196910506780709ULL;
|
||||
const uint64_t c = 1ULL;
|
||||
*seed = (a * (*seed) + c) % m;
|
||||
return (double) (*seed) / (double) m;
|
||||
}
|
||||
|
||||
uint64_t fast_forward_LCG(uint64_t seed, uint64_t n)
|
||||
{
|
||||
// LCG parameters
|
||||
const uint64_t m = 9223372036854775808ULL; // 2^63
|
||||
uint64_t a = 2806196910506780709ULL;
|
||||
uint64_t c = 1ULL;
|
||||
|
||||
n = n % m;
|
||||
|
||||
uint64_t a_new = 1;
|
||||
uint64_t c_new = 0;
|
||||
|
||||
while(n > 0)
|
||||
{
|
||||
if(n & 1)
|
||||
{
|
||||
a_new *= a;
|
||||
c_new = c_new * a + c;
|
||||
}
|
||||
c *= (a + 1);
|
||||
a *= a;
|
||||
|
||||
n >>= 1;
|
||||
}
|
||||
|
||||
return (a_new * seed + c_new) % m;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// OPTIMIZED VARIANT FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// This section contains a number of optimized variants of some of the above
|
||||
// functions, which each deploy a different combination of optimizations strategies.
|
||||
// By default, XSBench will not run any of these variants. They
|
||||
// must be specifically selected using the "-k <optimized variant ID>" command
|
||||
// line argument.
|
||||
//
|
||||
// As fast parallel sorting will be required for these optimizations, we will
|
||||
// first define a set of key-value parallel quicksort routines.
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Parallel Quicksort Key-Value Sorting Algorithms
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// These algorithms are based on the parallel quicksort implementation by
|
||||
// Eduard Lopez published at https://github.com/eduardlopez/quicksort-parallel
|
||||
//
|
||||
// Eduard's original version was for an integer type quicksort, but I have modified
|
||||
// it to form two different versions that can sort key-value pairs together without
|
||||
// having to bundle them into a separate object. Additionally, I have modified the
|
||||
// optimal chunk sizes and restricted the number of threads for the array sizing
|
||||
// that XSBench will be using by default.
|
||||
//
|
||||
// Eduard's original implementation carries the following license, which applies to
|
||||
// the following functions only:
|
||||
//
|
||||
// void quickSort_parallel_internal_i_d(int* key,double * value, int left, int right, int cutoff)
|
||||
// void quickSort_parallel_i_d(int* key,double * value, int lenArray, int numThreads)
|
||||
// void quickSort_parallel_internal_d_i(double* key,int * value, int left, int right, int cutoff)
|
||||
// void quickSort_parallel_d_i(double* key,int * value, int lenArray, int numThreads)
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016 Eduard López
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
void quickSort_parallel_internal_i_d(int* key,double * value, int left, int right, int cutoff)
|
||||
{
|
||||
int i = left, j = right;
|
||||
int tmp;
|
||||
int pivot = key[(left + right) / 2];
|
||||
|
||||
{
|
||||
while (i <= j) {
|
||||
while (key[i] < pivot)
|
||||
i++;
|
||||
while (key[j] > pivot)
|
||||
j--;
|
||||
if (i <= j) {
|
||||
tmp = key[i];
|
||||
key[i] = key[j];
|
||||
key[j] = tmp;
|
||||
double tmp_v = value[i];
|
||||
value[i] = value[j];
|
||||
value[j] = tmp_v;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ((right-left)<cutoff) ){
|
||||
if (left < j){ quickSort_parallel_internal_i_d(key, value, left, j, cutoff); }
|
||||
if (i < right){ quickSort_parallel_internal_i_d(key, value, i, right, cutoff); }
|
||||
|
||||
}else{
|
||||
#pragma omp task
|
||||
{ quickSort_parallel_internal_i_d(key, value, left, j, cutoff); }
|
||||
#pragma omp task
|
||||
{ quickSort_parallel_internal_i_d(key, value, i, right, cutoff); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void quickSort_parallel_i_d(int* key,double * value, int lenArray, int numThreads){
|
||||
|
||||
// Set minumum problem size to still spawn threads for
|
||||
int cutoff = 10000;
|
||||
|
||||
// For this problem size, more than 16 threads on CPU is not helpful
|
||||
if( numThreads > 16 )
|
||||
numThreads = 16;
|
||||
|
||||
#pragma omp parallel num_threads(numThreads)
|
||||
{
|
||||
#pragma omp single nowait
|
||||
{
|
||||
quickSort_parallel_internal_i_d(key,value, 0, lenArray-1, cutoff);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void quickSort_parallel_internal_d_i(double* key,int * value, int left, int right, int cutoff)
|
||||
{
|
||||
int i = left, j = right;
|
||||
double tmp;
|
||||
double pivot = key[(left + right) / 2];
|
||||
|
||||
{
|
||||
while (i <= j) {
|
||||
while (key[i] < pivot)
|
||||
i++;
|
||||
while (key[j] > pivot)
|
||||
j--;
|
||||
if (i <= j) {
|
||||
tmp = key[i];
|
||||
key[i] = key[j];
|
||||
key[j] = tmp;
|
||||
int tmp_v = value[i];
|
||||
value[i] = value[j];
|
||||
value[j] = tmp_v;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ((right-left)<cutoff) ){
|
||||
if (left < j){ quickSort_parallel_internal_d_i(key, value, left, j, cutoff); }
|
||||
if (i < right){ quickSort_parallel_internal_d_i(key, value, i, right, cutoff); }
|
||||
|
||||
}else{
|
||||
#pragma omp task
|
||||
{ quickSort_parallel_internal_d_i(key, value, left, j, cutoff); }
|
||||
#pragma omp task
|
||||
{ quickSort_parallel_internal_d_i(key, value, i, right, cutoff); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void quickSort_parallel_d_i(double* key,int * value, int lenArray, int numThreads){
|
||||
|
||||
// Set minumum problem size to still spawn threads for
|
||||
int cutoff = 10000;
|
||||
|
||||
// For this problem size, more than 16 threads on CPU is not helpful
|
||||
if( numThreads > 16 )
|
||||
numThreads = 16;
|
||||
|
||||
#pragma omp parallel num_threads(numThreads)
|
||||
{
|
||||
#pragma omp single nowait
|
||||
{
|
||||
quickSort_parallel_internal_d_i(key,value, 0, lenArray-1, cutoff);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Optimization 1 -- Event-based Sample/XS Lookup kernel splitting + Sorting
|
||||
// lookups by material and energy
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// This kernel separates out the sampling and lookup regions of the event-based
|
||||
// model, and then sorts the lookups by material type and energy. The goal of this
|
||||
// optimization is to allow for greatly improved cache locality, and XS indices
|
||||
// loaded from memory may be re-used for multiple lookups.
|
||||
//
|
||||
// As efficienct sorting is key for performance, we also must implement an
|
||||
// efficient key-value parallel sorting algorithm. We also experimented with using
|
||||
// the C++ version of thrust for these purposes, but found that our own implemtation
|
||||
// was slightly faster than the thrust library version, so for speed and
|
||||
// simplicity we will do not add the thrust dependency.
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
unsigned long long run_event_based_simulation_optimization_1(Inputs in, SimulationData SD, int mype)
|
||||
{
|
||||
char * optimization_name = "Optimization 1 - Kernel splitting + full material & energy sort";
|
||||
|
||||
if( mype == 0) printf("Simulation Kernel:\"%s\"\n", optimization_name);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Allocate Additional Data Structures Needed by Optimized Kernel
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
if( mype == 0) printf("Allocating additional data required by optimized kernel...\n");
|
||||
size_t sz;
|
||||
size_t total_sz = 0;
|
||||
double start, stop;
|
||||
|
||||
// loop variables
|
||||
int i = 0;
|
||||
int m = 0;
|
||||
|
||||
sz = in.lookups * sizeof(double);
|
||||
SD.p_energy_samples = (double *) malloc(sz);
|
||||
total_sz += sz;
|
||||
SD.length_p_energy_samples = in.lookups;
|
||||
|
||||
sz = in.lookups * sizeof(int);
|
||||
SD.mat_samples = (int *) malloc(sz);
|
||||
total_sz += sz;
|
||||
SD.length_mat_samples = in.lookups;
|
||||
|
||||
if( mype == 0) printf("Allocated an additional %.0lf MB of data on GPU.\n", total_sz/1024.0/1024.0);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin Actual Simulation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Sample Materials and Energies
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma omp parallel for schedule(dynamic, 100)
|
||||
for( i = 0; i < in.lookups; i++ )
|
||||
{
|
||||
// Set the initial seed value
|
||||
uint64_t seed = STARTING_SEED;
|
||||
|
||||
// Forward seed to lookup index (we need 2 samples per lookup)
|
||||
seed = fast_forward_LCG(seed, 2*i);
|
||||
|
||||
// Randomly pick an energy and material for the particle
|
||||
double p_energy = LCG_random_double(&seed);
|
||||
int mat = pick_mat(&seed);
|
||||
|
||||
SD.p_energy_samples[i] = p_energy;
|
||||
SD.mat_samples[i] = mat;
|
||||
}
|
||||
if(mype == 0) printf("finished sampling...\n");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Sort by Material
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
start = get_time();
|
||||
|
||||
quickSort_parallel_i_d(SD.mat_samples, SD.p_energy_samples, in.lookups, in.nthreads);
|
||||
|
||||
stop = get_time();
|
||||
|
||||
if(mype == 0) printf("Material sort took %.3lf seconds\n", stop-start);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Sort by Energy
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
start = get_time();
|
||||
|
||||
// Count up number of each type of sample.
|
||||
int num_samples_per_mat[12] = {0};
|
||||
for( int l = 0; l < in.lookups; l++ )
|
||||
num_samples_per_mat[ SD.mat_samples[l] ]++;
|
||||
|
||||
// Determine offsets
|
||||
int offsets[12] = {0};
|
||||
for( int m = 1; m < 12; m++ )
|
||||
offsets[m] = offsets[m-1] + num_samples_per_mat[m-1];
|
||||
|
||||
stop = get_time();
|
||||
if(mype == 0) printf("Counting samples and offsets took %.3lf seconds\n", stop-start);
|
||||
start = stop;
|
||||
|
||||
// Sort each material type by energy level
|
||||
int offset = 0;
|
||||
for( int m = 0; m < 12; m++ )
|
||||
quickSort_parallel_d_i(SD.p_energy_samples + offsets[m],SD.mat_samples + offsets[m], num_samples_per_mat[m], in.nthreads);
|
||||
|
||||
stop = get_time();
|
||||
if(mype == 0) printf("Energy Sorts took %.3lf seconds\n", stop-start);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Perform lookups for each material separately
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
start = get_time();
|
||||
|
||||
unsigned long long verification = 0;
|
||||
|
||||
// Individual Materials
|
||||
offset = 0;
|
||||
for( m = 0; m < 12; m++ )
|
||||
{
|
||||
#pragma omp parallel for schedule(dynamic,100) reduction(+:verification)
|
||||
for( i = offset; i < offset + num_samples_per_mat[m]; i++)
|
||||
{
|
||||
#ifdef AML
|
||||
int * num_nucs = aml_replicaset_hwloc_local_replica(SD.num_nucs_replica);
|
||||
double * concs = aml_replicaset_hwloc_local_replica(SD.concs_replica);
|
||||
double * unionized_energy_array = aml_replicaset_hwloc_local_replica(SD.unionized_energy_array_replica);
|
||||
int * index_grid = aml_replicaset_hwloc_local_replica(SD.index_grid_replica);
|
||||
NuclideGridPoint * nuclide_grid = aml_replicaset_hwloc_local_replica(SD.nuclide_grid_replica);
|
||||
#else
|
||||
int * num_nucs = SD.num_nucs;
|
||||
double * concs = SD.concs;
|
||||
double * unionized_energy_array = SD.unionized_energy_array;
|
||||
int * index_grid = SD.index_grid;
|
||||
NuclideGridPoint * nuclide_grid = SD.nuclide_grid;
|
||||
#endif
|
||||
|
||||
// load pre-sampled energy and material for the particle
|
||||
double p_energy = SD.p_energy_samples[i];
|
||||
int mat = SD.mat_samples[i];
|
||||
|
||||
double macro_xs_vector[5] = {0};
|
||||
|
||||
// Perform macroscopic Cross Section Lookup
|
||||
calculate_macro_xs(
|
||||
p_energy, // Sampled neutron energy (in lethargy)
|
||||
mat, // Sampled material type index neutron is in
|
||||
in.n_isotopes, // Total number of isotopes in simulation
|
||||
in.n_gridpoints, // Number of gridpoints per isotope in simulation
|
||||
num_nucs, // 1-D array with number of nuclides per material
|
||||
concs, // Flattened 2-D array with concentration of each nuclide in each material
|
||||
unionized_energy_array, // 1-D Unionized energy array
|
||||
index_grid, // Flattened 2-D grid holding indices into nuclide grid for each unionized energy level
|
||||
nuclide_grid, // Flattened 2-D grid holding energy levels and XS_data for all nuclides in simulation
|
||||
SD.mats, // Flattened 2-D array with nuclide indices defining composition of each type of material
|
||||
macro_xs_vector, // 1-D array with result of the macroscopic cross section (5 different reaction channels)
|
||||
in.grid_type, // Lookup type (nuclide, hash, or unionized)
|
||||
in.hash_bins, // Number of hash bins used (if using hash lookup type)
|
||||
SD.max_num_nucs // Maximum number of nuclides present in any material
|
||||
);
|
||||
|
||||
// For verification, and to prevent the compiler from optimizing
|
||||
// all work out, we interrogate the returned macro_xs_vector array
|
||||
// to find its maximum value index, then increment the verification
|
||||
// value by that index. In this implementation, we prevent thread
|
||||
// contention by using an OMP reduction on the verification value.
|
||||
// For accelerators, a different approach might be required
|
||||
// (e.g., atomics, reduction of thread-specific values in large
|
||||
// array via CUDA thrust, etc).
|
||||
double max = -1.0;
|
||||
int max_idx = 0;
|
||||
for(int j = 0; j < 5; j++ )
|
||||
{
|
||||
if( macro_xs_vector[j] > max )
|
||||
{
|
||||
max = macro_xs_vector[j];
|
||||
max_idx = j;
|
||||
}
|
||||
}
|
||||
verification += max_idx+1;
|
||||
}
|
||||
offset += num_samples_per_mat[m];
|
||||
}
|
||||
|
||||
stop = get_time();
|
||||
if(mype == 0) printf("XS Lookups took %.3lf seconds\n", stop-start);
|
||||
return verification;
|
||||
}
|
||||
BIN
benchmarks/benchmarks/XSbench/Simulations.o
Normal file
BIN
benchmarks/benchmarks/XSbench/Simulations.o
Normal file
Binary file not shown.
BIN
benchmarks/benchmarks/XSbench/XSBench
Executable file
BIN
benchmarks/benchmarks/XSbench/XSBench
Executable file
Binary file not shown.
151
benchmarks/benchmarks/XSbench/XSbench_header.h
Normal file
151
benchmarks/benchmarks/XSbench/XSbench_header.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#ifndef __XSBENCH_HEADER_H__
|
||||
#define __XSBENCH_HEADER_H__
|
||||
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<time.h>
|
||||
#include<string.h>
|
||||
#include<math.h>
|
||||
#include<assert.h>
|
||||
#include<stdint.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#else
|
||||
#include<unistd.h>
|
||||
#include<sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENMP
|
||||
#include<omp.h>
|
||||
#endif
|
||||
|
||||
// Papi Header
|
||||
#ifdef PAPI
|
||||
#include "papi.h"
|
||||
#endif
|
||||
|
||||
//AML header
|
||||
#ifdef AML
|
||||
#include<aml.h>
|
||||
#include<aml/higher/replicaset.h>
|
||||
#include<aml/higher/replicaset/hwloc.h>
|
||||
#endif
|
||||
|
||||
// Grid types
|
||||
#define UNIONIZED 0
|
||||
#define NUCLIDE 1
|
||||
#define HASH 2
|
||||
|
||||
// Simulation types
|
||||
#define HISTORY_BASED 1
|
||||
#define EVENT_BASED 2
|
||||
|
||||
// Binary Mode Type
|
||||
#define NONE 0
|
||||
#define READ 1
|
||||
#define WRITE 2
|
||||
|
||||
// Starting Seed
|
||||
#define STARTING_SEED 1070
|
||||
|
||||
// Structures
|
||||
typedef struct{
|
||||
double energy;
|
||||
double total_xs;
|
||||
double elastic_xs;
|
||||
double absorbtion_xs;
|
||||
double fission_xs;
|
||||
double nu_fission_xs;
|
||||
} NuclideGridPoint;
|
||||
|
||||
typedef struct{
|
||||
int nthreads;
|
||||
long n_isotopes;
|
||||
long n_gridpoints;
|
||||
int lookups;
|
||||
char * HM;
|
||||
int grid_type; // 0: Unionized Grid (default) 1: Nuclide Grid
|
||||
int hash_bins;
|
||||
int particles;
|
||||
int simulation_method;
|
||||
int binary_mode;
|
||||
int kernel_id;
|
||||
} Inputs;
|
||||
|
||||
typedef struct{
|
||||
int * num_nucs; // Length = length_num_nucs;
|
||||
double * concs; // Length = length_concs
|
||||
int * mats; // Length = length_mats
|
||||
double * unionized_energy_array; // Length = length_unionized_energy_array
|
||||
int * index_grid; // Length = length_index_grid
|
||||
NuclideGridPoint * nuclide_grid; // Length = length_nuclide_grid
|
||||
#ifdef AML
|
||||
struct aml_replicaset * num_nucs_replica;
|
||||
struct aml_replicaset * concs_replica;
|
||||
struct aml_replicaset * unionized_energy_array_replica;
|
||||
struct aml_replicaset * index_grid_replica;
|
||||
struct aml_replicaset * nuclide_grid_replica;
|
||||
#endif
|
||||
int length_num_nucs;
|
||||
int length_concs;
|
||||
int length_mats;
|
||||
int length_unionized_energy_array;
|
||||
long length_index_grid;
|
||||
int length_nuclide_grid;
|
||||
int max_num_nucs;
|
||||
double * p_energy_samples;
|
||||
int length_p_energy_samples;
|
||||
int * mat_samples;
|
||||
int length_mat_samples;
|
||||
} SimulationData;
|
||||
|
||||
// io.c
|
||||
void logo(int version);
|
||||
void center_print(const char *s, int width);
|
||||
void border_print(void);
|
||||
void fancy_int(long a);
|
||||
Inputs read_CLI( int argc, char * argv[] );
|
||||
void print_CLI_error(void);
|
||||
void print_inputs(Inputs in, int nprocs, int version);
|
||||
int print_results( Inputs in, int mype, double runtime, int nprocs, unsigned long long vhash );
|
||||
void binary_write( Inputs in, SimulationData SD );
|
||||
SimulationData binary_read( Inputs in );
|
||||
|
||||
// Simulation.c
|
||||
unsigned long long run_event_based_simulation(Inputs in, SimulationData SD, int mype);
|
||||
unsigned long long run_history_based_simulation(Inputs in, SimulationData SD, int mype);
|
||||
void calculate_micro_xs( double p_energy, int nuc, long n_isotopes,
|
||||
long n_gridpoints,
|
||||
double * restrict egrid, int * restrict index_data,
|
||||
NuclideGridPoint * restrict nuclide_grids,
|
||||
long idx, double * restrict xs_vector, int grid_type, int hash_bins );
|
||||
void calculate_macro_xs( double p_energy, int mat, long n_isotopes,
|
||||
long n_gridpoints, int * restrict num_nucs,
|
||||
double * restrict concs,
|
||||
double * restrict egrid, int * restrict index_data,
|
||||
NuclideGridPoint * restrict nuclide_grids,
|
||||
int * restrict mats,
|
||||
double * restrict macro_xs_vector, int grid_type, int hash_bins, int max_num_nucs );
|
||||
long grid_search( long n, double quarry, double * restrict A);
|
||||
long grid_search_nuclide( long n, double quarry, NuclideGridPoint * A, long low, long high);
|
||||
int pick_mat( uint64_t * seed );
|
||||
double LCG_random_double(uint64_t * seed);
|
||||
uint64_t fast_forward_LCG(uint64_t seed, uint64_t n);
|
||||
unsigned long long run_event_based_simulation_optimization_1(Inputs in, SimulationData SD, int mype);
|
||||
|
||||
// GridInit.c
|
||||
SimulationData grid_init_do_not_profile( Inputs in, int mype );
|
||||
|
||||
// XSutils.c
|
||||
int NGP_compare( const void * a, const void * b );
|
||||
int double_compare(const void * a, const void * b);
|
||||
size_t estimate_mem_usage( Inputs in );
|
||||
double get_time(void);
|
||||
|
||||
// Materials.c
|
||||
int * load_num_nucs(long n_isotopes);
|
||||
int * load_mats( int * num_nucs, long n_isotopes, int * max_num_nucs );
|
||||
double * load_concs( int * num_nucs, int max_num_nucs );
|
||||
#endif
|
||||
63
benchmarks/benchmarks/XSbench/XSutils.c
Normal file
63
benchmarks/benchmarks/XSbench/XSutils.c
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "XSbench_header.h"
|
||||
|
||||
int double_compare(const void * a, const void * b)
|
||||
{
|
||||
double A = *((double *) a);
|
||||
double B = *((double *) b);
|
||||
|
||||
if( A > B )
|
||||
return 1;
|
||||
else if( A < B )
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NGP_compare(const void * a, const void * b)
|
||||
{
|
||||
NuclideGridPoint A = *((NuclideGridPoint *) a);
|
||||
NuclideGridPoint B = *((NuclideGridPoint *) b);
|
||||
|
||||
if( A.energy > B.energy )
|
||||
return 1;
|
||||
else if( A.energy < B.energy )
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t estimate_mem_usage( Inputs in )
|
||||
{
|
||||
size_t single_nuclide_grid = in.n_gridpoints * sizeof( NuclideGridPoint );
|
||||
size_t all_nuclide_grids = in.n_isotopes * single_nuclide_grid;
|
||||
size_t size_UEG = in.n_isotopes*in.n_gridpoints*sizeof(double) + in.n_isotopes*in.n_gridpoints*in.n_isotopes*sizeof(int);
|
||||
size_t size_hash_grid = in.hash_bins * in.n_isotopes * sizeof(int);
|
||||
size_t memtotal;
|
||||
|
||||
if( in.grid_type == UNIONIZED )
|
||||
memtotal = all_nuclide_grids + size_UEG;
|
||||
else if( in.grid_type == NUCLIDE )
|
||||
memtotal = all_nuclide_grids;
|
||||
else
|
||||
memtotal = all_nuclide_grids + size_hash_grid;
|
||||
|
||||
memtotal = ceil(memtotal / (1024.0*1024.0));
|
||||
return memtotal;
|
||||
}
|
||||
|
||||
double get_time(void)
|
||||
{
|
||||
#ifdef OPENMP
|
||||
return omp_get_wtime();
|
||||
#endif
|
||||
|
||||
struct timeval timecheck;
|
||||
|
||||
gettimeofday(&timecheck, NULL);
|
||||
long ms = (long)timecheck.tv_sec * 1000 + (long)timecheck.tv_usec / 1000;
|
||||
|
||||
double time = (double) ms / 1000.0;
|
||||
|
||||
return time;
|
||||
}
|
||||
BIN
benchmarks/benchmarks/XSbench/XSutils.o
Normal file
BIN
benchmarks/benchmarks/XSbench/XSutils.o
Normal file
Binary file not shown.
508
benchmarks/benchmarks/XSbench/io.c
Normal file
508
benchmarks/benchmarks/XSbench/io.c
Normal file
@@ -0,0 +1,508 @@
|
||||
#include "XSbench_header.h"
|
||||
|
||||
#ifdef MPI
|
||||
#include<mpi.h>
|
||||
#endif
|
||||
|
||||
// Prints program logo
|
||||
void logo(int version)
|
||||
{
|
||||
border_print();
|
||||
printf(
|
||||
" __ __ ___________ _ \n"
|
||||
" \\ \\ / // ___| ___ \\ | | \n"
|
||||
" \\ V / \\ `--.| |_/ / ___ _ __ ___| |__ \n"
|
||||
" / \\ `--. \\ ___ \\/ _ \\ '_ \\ / __| '_ \\ \n"
|
||||
" / /^\\ \\/\\__/ / |_/ / __/ | | | (__| | | | \n"
|
||||
" \\/ \\/\\____/\\____/ \\___|_| |_|\\___|_| |_| \n\n"
|
||||
);
|
||||
border_print();
|
||||
center_print("Developed at Argonne National Laboratory", 79);
|
||||
char v[100];
|
||||
sprintf(v, "Version: %d", version);
|
||||
center_print(v, 79);
|
||||
border_print();
|
||||
}
|
||||
|
||||
// Prints Section titles in center of 80 char terminal
|
||||
void center_print(const char *s, int width)
|
||||
{
|
||||
int length = strlen(s);
|
||||
int i;
|
||||
for (i=0; i<=(width-length)/2; i++) {
|
||||
fputs(" ", stdout);
|
||||
}
|
||||
fputs(s, stdout);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
|
||||
int print_results( Inputs in, int mype, double runtime, int nprocs,
|
||||
unsigned long long vhash )
|
||||
{
|
||||
// Calculate Lookups per sec
|
||||
int lookups = 0;
|
||||
if( in.simulation_method == HISTORY_BASED )
|
||||
lookups = in.lookups * in.particles;
|
||||
else if( in.simulation_method == EVENT_BASED )
|
||||
lookups = in.lookups;
|
||||
int lookups_per_sec = (int) ((double) lookups / runtime);
|
||||
|
||||
// If running in MPI, reduce timing statistics and calculate average
|
||||
#ifdef MPI
|
||||
int total_lookups = 0;
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
MPI_Reduce(&lookups_per_sec, &total_lookups, 1, MPI_INT,
|
||||
MPI_SUM, 0, MPI_COMM_WORLD);
|
||||
#endif
|
||||
|
||||
int is_invalid_result = 1;
|
||||
|
||||
// Print output
|
||||
if( mype == 0 )
|
||||
{
|
||||
border_print();
|
||||
center_print("RESULTS", 79);
|
||||
border_print();
|
||||
|
||||
// Print the results
|
||||
printf("Threads: %d\n", in.nthreads);
|
||||
#ifdef MPI
|
||||
printf("MPI ranks: %d\n", nprocs);
|
||||
#endif
|
||||
#ifdef MPI
|
||||
printf("Total Lookups/s: ");
|
||||
fancy_int(total_lookups);
|
||||
printf("Avg Lookups/s per MPI rank: ");
|
||||
fancy_int(total_lookups / nprocs);
|
||||
#else
|
||||
printf("Runtime: %.3lf seconds\n", runtime);
|
||||
printf("Lookups: "); fancy_int(lookups);
|
||||
printf("Lookups/s: ");
|
||||
fancy_int(lookups_per_sec);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long long large = 0;
|
||||
unsigned long long small = 0;
|
||||
if( in.simulation_method == EVENT_BASED )
|
||||
{
|
||||
small = 945990;
|
||||
large = 952131;
|
||||
}
|
||||
else if( in.simulation_method == HISTORY_BASED )
|
||||
{
|
||||
small = 941535;
|
||||
large = 954318;
|
||||
}
|
||||
if( strcmp(in.HM, "large") == 0 )
|
||||
{
|
||||
if( vhash == large )
|
||||
is_invalid_result = 0;
|
||||
}
|
||||
else if( strcmp(in.HM, "small") == 0 )
|
||||
{
|
||||
if( vhash == small )
|
||||
is_invalid_result = 0;
|
||||
}
|
||||
|
||||
if(mype == 0 )
|
||||
{
|
||||
if( is_invalid_result )
|
||||
printf("Verification checksum: %llu (WARNING - INVALID CHECKSUM!)\n", vhash);
|
||||
else
|
||||
printf("Verification checksum: %llu (Valid)\n", vhash);
|
||||
border_print();
|
||||
}
|
||||
|
||||
return is_invalid_result;
|
||||
}
|
||||
|
||||
void print_inputs(Inputs in, int nprocs, int version )
|
||||
{
|
||||
// Calculate Estimate of Memory Usage
|
||||
int mem_tot = estimate_mem_usage( in );
|
||||
logo(version);
|
||||
center_print("INPUT SUMMARY", 79);
|
||||
border_print();
|
||||
if( in.simulation_method == EVENT_BASED )
|
||||
printf("Simulation Method: Event Based\n");
|
||||
else
|
||||
printf("Simulation Method: History Based\n");
|
||||
if( in.grid_type == NUCLIDE )
|
||||
printf("Grid Type: Nuclide Grid\n");
|
||||
else if( in.grid_type == UNIONIZED )
|
||||
printf("Grid Type: Unionized Grid\n");
|
||||
else
|
||||
printf("Grid Type: Hash\n");
|
||||
|
||||
printf("Materials: %d\n", 12);
|
||||
printf("H-M Benchmark Size: %s\n", in.HM);
|
||||
printf("Total Nuclides: %ld\n", in.n_isotopes);
|
||||
printf("Gridpoints (per Nuclide): ");
|
||||
fancy_int(in.n_gridpoints);
|
||||
if( in.grid_type == HASH )
|
||||
{
|
||||
printf("Hash Bins: ");
|
||||
fancy_int(in.hash_bins);
|
||||
}
|
||||
if( in.grid_type == UNIONIZED )
|
||||
{
|
||||
printf("Unionized Energy Gridpoints: ");
|
||||
fancy_int(in.n_isotopes*in.n_gridpoints);
|
||||
}
|
||||
if( in.simulation_method == HISTORY_BASED )
|
||||
{
|
||||
printf("Particle Histories: "); fancy_int(in.particles);
|
||||
printf("XS Lookups per Particle: "); fancy_int(in.lookups);
|
||||
}
|
||||
printf("Total XS Lookups: "); fancy_int(in.lookups);
|
||||
#ifdef MPI
|
||||
printf("MPI Ranks: %d\n", nprocs);
|
||||
printf("OMP Threads per MPI Rank: %d\n", in.nthreads);
|
||||
printf("Mem Usage per MPI Rank (MB): "); fancy_int(mem_tot);
|
||||
#else
|
||||
printf("Threads: %d\n", in.nthreads);
|
||||
printf("Est. Memory Usage (MB): "); fancy_int(mem_tot);
|
||||
#endif
|
||||
printf("Binary File Mode: ");
|
||||
if( in.binary_mode == NONE )
|
||||
printf("Off\n");
|
||||
else if( in.binary_mode == READ)
|
||||
printf("Read\n");
|
||||
else
|
||||
printf("Write\n");
|
||||
border_print();
|
||||
center_print("INITIALIZATION - DO NOT PROFILE", 79);
|
||||
border_print();
|
||||
}
|
||||
|
||||
void border_print(void)
|
||||
{
|
||||
printf(
|
||||
"==================================================================="
|
||||
"=============\n");
|
||||
}
|
||||
|
||||
// Prints comma separated integers - for ease of reading
|
||||
void fancy_int( long a )
|
||||
{
|
||||
if( a < 1000 )
|
||||
printf("%ld\n",a);
|
||||
|
||||
else if( a >= 1000 && a < 1000000 )
|
||||
printf("%ld,%03ld\n", a / 1000, a % 1000);
|
||||
|
||||
else if( a >= 1000000 && a < 1000000000 )
|
||||
printf("%ld,%03ld,%03ld\n",a / 1000000,(a % 1000000) / 1000,a % 1000 );
|
||||
|
||||
else if( a >= 1000000000 )
|
||||
printf("%ld,%03ld,%03ld,%03ld\n",
|
||||
a / 1000000000,
|
||||
(a % 1000000000) / 1000000,
|
||||
(a % 1000000) / 1000,
|
||||
a % 1000 );
|
||||
else
|
||||
printf("%ld\n",a);
|
||||
}
|
||||
|
||||
void print_CLI_error(void)
|
||||
{
|
||||
printf("Usage: ./XSBench <options>\n");
|
||||
printf("Options include:\n");
|
||||
printf(" -m <simulation method> Simulation method (history, event)\n");
|
||||
printf(" -t <threads> Number of OpenMP threads to run\n");
|
||||
printf(" -s <size> Size of H-M Benchmark to run (small, large, XL, XXL)\n");
|
||||
printf(" -g <gridpoints> Number of gridpoints per nuclide (overrides -s defaults)\n");
|
||||
printf(" -G <grid type> Grid search type (unionized, nuclide, hash). Defaults to unionized.\n");
|
||||
printf(" -p <particles> Number of particle histories\n");
|
||||
printf(" -l <lookups> History Based: Number of Cross-section (XS) lookups per particle. Event Based: Total number of XS lookups.\n");
|
||||
printf(" -h <hash bins> Number of hash bins (only relevant when used with \"-G hash\")\n");
|
||||
printf(" -b <binary mode> Read or write all data structures to file. If reading, this will skip initialization phase. (read, write)\n");
|
||||
printf(" -k <kernel ID> Specifies which kernel to run. 0 is baseline, 1, 2, etc are optimized variants. (0 is default.)\n");
|
||||
printf("Default is equivalent to: -m history -s large -l 34 -p 500000 -G unionized\n");
|
||||
printf("See readme for full description of default run values\n");
|
||||
exit(4);
|
||||
}
|
||||
|
||||
Inputs read_CLI( int argc, char * argv[] )
|
||||
{
|
||||
Inputs input;
|
||||
|
||||
// defaults to the history based simulation method
|
||||
input.simulation_method = HISTORY_BASED;
|
||||
|
||||
// defaults to max threads on the system
|
||||
#ifdef OPENMP
|
||||
input.nthreads = omp_get_num_procs();
|
||||
#else
|
||||
input.nthreads = 1;
|
||||
#endif
|
||||
|
||||
// defaults to 355 (corresponding to H-M Large benchmark)
|
||||
input.n_isotopes = 355;
|
||||
|
||||
// defaults to 11303 (corresponding to H-M Large benchmark)
|
||||
input.n_gridpoints = 11303;
|
||||
|
||||
// defaults to 500,000
|
||||
input.particles = 500000;
|
||||
|
||||
// defaults to 34
|
||||
input.lookups = 34;
|
||||
|
||||
// default to unionized grid
|
||||
input.grid_type = UNIONIZED;
|
||||
|
||||
// default to unionized grid
|
||||
input.hash_bins = 10000;
|
||||
|
||||
// default to no binary read/write
|
||||
input.binary_mode = NONE;
|
||||
|
||||
// defaults to baseline kernel
|
||||
input.kernel_id = 0;
|
||||
|
||||
// defaults to H-M Large benchmark
|
||||
input.HM = (char *) malloc( 6 * sizeof(char) );
|
||||
input.HM[0] = 'l' ;
|
||||
input.HM[1] = 'a' ;
|
||||
input.HM[2] = 'r' ;
|
||||
input.HM[3] = 'g' ;
|
||||
input.HM[4] = 'e' ;
|
||||
input.HM[5] = '\0';
|
||||
|
||||
// Check if user sets these
|
||||
int user_g = 0;
|
||||
|
||||
int default_lookups = 1;
|
||||
int default_particles = 1;
|
||||
|
||||
// Collect Raw Input
|
||||
for( int i = 1; i < argc; i++ )
|
||||
{
|
||||
char * arg = argv[i];
|
||||
|
||||
// nthreads (-t)
|
||||
if( strcmp(arg, "-t") == 0 )
|
||||
{
|
||||
if( ++i < argc )
|
||||
input.nthreads = atoi(argv[i]);
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// n_gridpoints (-g)
|
||||
else if( strcmp(arg, "-g") == 0 )
|
||||
{
|
||||
if( ++i < argc )
|
||||
{
|
||||
user_g = 1;
|
||||
input.n_gridpoints = atol(argv[i]);
|
||||
}
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// Simulation Method (-m)
|
||||
else if( strcmp(arg, "-m") == 0 )
|
||||
{
|
||||
char * sim_type;
|
||||
if( ++i < argc )
|
||||
sim_type = argv[i];
|
||||
else
|
||||
print_CLI_error();
|
||||
|
||||
if( strcmp(sim_type, "history") == 0 )
|
||||
input.simulation_method = HISTORY_BASED;
|
||||
else if( strcmp(sim_type, "event") == 0 )
|
||||
{
|
||||
input.simulation_method = EVENT_BASED;
|
||||
// Also resets default # of lookups
|
||||
if( default_lookups && default_particles )
|
||||
{
|
||||
input.lookups = input.lookups * input.particles;
|
||||
input.particles = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// lookups (-l)
|
||||
else if( strcmp(arg, "-l") == 0 )
|
||||
{
|
||||
if( ++i < argc )
|
||||
{
|
||||
input.lookups = atoi(argv[i]);
|
||||
default_lookups = 0;
|
||||
}
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// hash bins (-h)
|
||||
else if( strcmp(arg, "-h") == 0 )
|
||||
{
|
||||
if( ++i < argc )
|
||||
input.hash_bins = atoi(argv[i]);
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// particles (-p)
|
||||
else if( strcmp(arg, "-p") == 0 )
|
||||
{
|
||||
if( ++i < argc )
|
||||
{
|
||||
input.particles = atoi(argv[i]);
|
||||
default_particles = 0;
|
||||
}
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// HM (-s)
|
||||
else if( strcmp(arg, "-s") == 0 )
|
||||
{
|
||||
if( ++i < argc )
|
||||
input.HM = argv[i];
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// grid type (-G)
|
||||
else if( strcmp(arg, "-G") == 0 )
|
||||
{
|
||||
char * grid_type;
|
||||
if( ++i < argc )
|
||||
grid_type = argv[i];
|
||||
else
|
||||
print_CLI_error();
|
||||
|
||||
if( strcmp(grid_type, "unionized") == 0 )
|
||||
input.grid_type = UNIONIZED;
|
||||
else if( strcmp(grid_type, "nuclide") == 0 )
|
||||
input.grid_type = NUCLIDE;
|
||||
else if( strcmp(grid_type, "hash") == 0 )
|
||||
input.grid_type = HASH;
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// binary mode (-b)
|
||||
else if( strcmp(arg, "-b") == 0 )
|
||||
{
|
||||
char * binary_mode;
|
||||
if( ++i < argc )
|
||||
binary_mode = argv[i];
|
||||
else
|
||||
print_CLI_error();
|
||||
|
||||
if( strcmp(binary_mode, "read") == 0 )
|
||||
input.binary_mode = READ;
|
||||
else if( strcmp(binary_mode, "write") == 0 )
|
||||
input.binary_mode = WRITE;
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
// kernel optimization selection (-k)
|
||||
else if( strcmp(arg, "-k") == 0 )
|
||||
{
|
||||
if( ++i < argc )
|
||||
{
|
||||
input.kernel_id = atoi(argv[i]);
|
||||
}
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
else
|
||||
print_CLI_error();
|
||||
}
|
||||
|
||||
// Validate Input
|
||||
|
||||
// Validate nthreads
|
||||
if( input.nthreads < 1 )
|
||||
print_CLI_error();
|
||||
|
||||
// Validate n_isotopes
|
||||
if( input.n_isotopes < 1 )
|
||||
print_CLI_error();
|
||||
|
||||
// Validate n_gridpoints
|
||||
if( input.n_gridpoints < 1 )
|
||||
print_CLI_error();
|
||||
|
||||
// Validate lookups
|
||||
if( input.lookups < 1 )
|
||||
print_CLI_error();
|
||||
|
||||
// Validate Hash Bins
|
||||
if( input.hash_bins < 1 )
|
||||
print_CLI_error();
|
||||
|
||||
// Validate HM size
|
||||
if( strcasecmp(input.HM, "small") != 0 &&
|
||||
strcasecmp(input.HM, "large") != 0 &&
|
||||
strcasecmp(input.HM, "XL") != 0 &&
|
||||
strcasecmp(input.HM, "XXL") != 0 )
|
||||
print_CLI_error();
|
||||
|
||||
// Set HM size specific parameters
|
||||
// (defaults to large)
|
||||
if( strcasecmp(input.HM, "small") == 0 )
|
||||
input.n_isotopes = 68;
|
||||
else if( strcasecmp(input.HM, "XL") == 0 && user_g == 0 )
|
||||
input.n_gridpoints = 238847; // sized to make 120 GB XS data
|
||||
else if( strcasecmp(input.HM, "XXL") == 0 && user_g == 0 )
|
||||
input.n_gridpoints = 238847 * 2.1; // 252 GB XS data
|
||||
|
||||
// Return input struct
|
||||
return input;
|
||||
}
|
||||
|
||||
void binary_write( Inputs in, SimulationData SD )
|
||||
{
|
||||
char * fname = "XS_data.dat";
|
||||
printf("Writing all data structures to binary file %s...\n", fname);
|
||||
FILE * fp = fopen(fname, "w");
|
||||
|
||||
// Write SimulationData Object. Include pointers, even though we won't be using them.
|
||||
fwrite(&SD, sizeof(SimulationData), 1, fp);
|
||||
|
||||
// Write heap arrays in SimulationData Object
|
||||
fwrite(SD.num_nucs, sizeof(int), SD.length_num_nucs, fp);
|
||||
fwrite(SD.concs, sizeof(double), SD.length_concs, fp);
|
||||
fwrite(SD.mats, sizeof(int), SD.length_mats, fp);
|
||||
fwrite(SD.nuclide_grid, sizeof(NuclideGridPoint), SD.length_nuclide_grid, fp);
|
||||
fwrite(SD.index_grid, sizeof(int), SD.length_index_grid, fp);
|
||||
fwrite(SD.unionized_energy_array, sizeof(double), SD.length_unionized_energy_array, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
SimulationData binary_read( Inputs in )
|
||||
{
|
||||
SimulationData SD;
|
||||
|
||||
char * fname = "XS_data.dat";
|
||||
printf("Reading all data structures from binary file %s...\n", fname);
|
||||
|
||||
FILE * fp = fopen(fname, "r");
|
||||
assert(fp != NULL);
|
||||
|
||||
// Read SimulationData Object. Include pointers, even though we won't be using them.
|
||||
fread(&SD, sizeof(SimulationData), 1, fp);
|
||||
|
||||
// Allocate space for arrays on heap
|
||||
SD.num_nucs = (int *) malloc(SD.length_num_nucs * sizeof(int));
|
||||
SD.concs = (double *) malloc(SD.length_concs * sizeof(double));
|
||||
SD.mats = (int *) malloc(SD.length_mats * sizeof(int));
|
||||
SD.nuclide_grid = (NuclideGridPoint *) malloc(SD.length_nuclide_grid * sizeof(NuclideGridPoint));
|
||||
SD.index_grid = (int *) malloc( SD.length_index_grid * sizeof(int));
|
||||
SD.unionized_energy_array = (double *) malloc( SD.length_unionized_energy_array * sizeof(double));
|
||||
|
||||
// Read heap arrays into SimulationData Object
|
||||
fread(SD.num_nucs, sizeof(int), SD.length_num_nucs, fp);
|
||||
fread(SD.concs, sizeof(double), SD.length_concs, fp);
|
||||
fread(SD.mats, sizeof(int), SD.length_mats, fp);
|
||||
fread(SD.nuclide_grid, sizeof(NuclideGridPoint), SD.length_nuclide_grid, fp);
|
||||
fread(SD.index_grid, sizeof(int), SD.length_index_grid, fp);
|
||||
fread(SD.unionized_energy_array, sizeof(double), SD.length_unionized_energy_array, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return SD;
|
||||
}
|
||||
BIN
benchmarks/benchmarks/XSbench/io.o
Normal file
BIN
benchmarks/benchmarks/XSbench/io.o
Normal file
Binary file not shown.
116
benchmarks/benchmarks/cfrac/CMakeLists.txt
Normal file
116
benchmarks/benchmarks/cfrac/CMakeLists.txt
Normal file
@@ -0,0 +1,116 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(mimalloc-bench CXX C)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "No build type selected, default to *** Release ***")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
FUNCTION(PREPEND var prefix)
|
||||
SET(listVar "")
|
||||
FOREACH(f ${ARGN})
|
||||
LIST(APPEND listVar "${prefix}/${f}")
|
||||
ENDFOREACH(f)
|
||||
SET(${var} "${listVar}" PARENT_SCOPE)
|
||||
ENDFUNCTION(PREPEND)
|
||||
|
||||
set(cfrac_sources
|
||||
cfrac.c
|
||||
pops.c pconst.c pio.c
|
||||
pabs.c pneg.c pcmp.c podd.c phalf.c
|
||||
padd.c psub.c pmul.c pdivmod.c psqrt.c ppowmod.c
|
||||
atop.c ptoa.c itop.c utop.c ptou.c errorp.c
|
||||
pfloat.c pidiv.c pimod.c picmp.c
|
||||
primes.c pcfrac.c pgcd.c)
|
||||
PREPEND(cfrac_sources . ${cfrac_sources})
|
||||
|
||||
# set(espresso_sources
|
||||
# cofactor.c cols.c compl.c contain.c cubestr.c cvrin.c cvrm.c cvrmisc.c cvrout.c
|
||||
# dominate.c equiv.c espresso.c essen.c exact.c expand.c gasp.c getopt.c gimpel.c
|
||||
# globals.c hack.c indep.c irred.c main.c map.c matrix.c mincov.c opo.c pair.c part.c
|
||||
# primes.c reduce.c rows.c set.c setc.c sharp.c sminterf.c solution.c sparse.c unate.c
|
||||
# utility.c verify.c)
|
||||
# PREPEND(espresso_sources . ${espresso_sources})
|
||||
|
||||
# set(barnes_sources
|
||||
# code.c code_io.c load.c grav.c getparam.c util.c)
|
||||
# PREPEND(barnes_sources barnes/ ${barnes_sources})
|
||||
|
||||
# turn off warnings..
|
||||
message(STATUS "${CMAKE_C_COMPILER_ID}")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
|
||||
set(FLAGS " -w -Wno-implicit-function-declaration -Wno-implicit-int -Wno-int-conversion -Wno-return-mismatch -Wno-incompatible-pointer-types -mabi=purecap-benchmark")
|
||||
string(APPEND CMAKE_C_FLAGS ${FLAGS})
|
||||
string(APPEND CMAKE_CXX_FLAGS ${FLAGS})
|
||||
endif()
|
||||
|
||||
add_executable(cfrac ${cfrac_sources})
|
||||
target_compile_options(cfrac PRIVATE $<$<C_COMPILER_ID:GNU>:-std=gnu89>)
|
||||
target_compile_definitions(cfrac PRIVATE NOMEMOPT=1)
|
||||
target_link_libraries(cfrac m)
|
||||
|
||||
# add_executable(espresso ${espresso_sources})
|
||||
# target_compile_options(espresso PRIVATE $<$<C_COMPILER_ID:GNU>:-std=gnu89>)
|
||||
# target_link_libraries(espresso m)
|
||||
|
||||
# add_executable(barnes ${barnes_sources})
|
||||
# target_link_libraries(barnes m)
|
||||
|
||||
# add_executable(larson larson/larson.cpp)
|
||||
# target_compile_options(larson PRIVATE -Wno-unused-result)
|
||||
# target_compile_definitions(larson PRIVATE CPP=1)
|
||||
# target_link_libraries(larson pthread)
|
||||
|
||||
# add_executable(larson-sized larson/larson.cpp)
|
||||
# target_compile_options(larson-sized PRIVATE -Wno-unused-result -fsized-deallocation)
|
||||
# target_compile_definitions(larson-sized PRIVATE CPP=1 SIZED=1)
|
||||
# target_link_libraries(larson-sized pthread)
|
||||
|
||||
# add_executable(alloc-test alloc-test/test_common.cpp alloc-test/allocator_tester.cpp)
|
||||
# target_compile_definitions(alloc-test PRIVATE BENCH=4)
|
||||
# target_link_libraries(alloc-test pthread)
|
||||
|
||||
# if(NOT APPLE)
|
||||
# add_executable(sh6bench shbench/sh6bench-new.c)
|
||||
# target_compile_definitions(sh6bench PRIVATE BENCH=1 SYS_MULTI_THREAD=1)
|
||||
# target_link_libraries(sh6bench pthread)
|
||||
|
||||
# add_executable(sh8bench shbench/sh8bench-new.c)
|
||||
# target_compile_definitions(sh8bench PRIVATE BENCH=1 SYS_MULTI_THREAD=1)
|
||||
# target_link_libraries(sh8bench pthread)
|
||||
# endif()
|
||||
|
||||
# add_executable(cache-scratch cache-scratch/cache-scratch.cpp)
|
||||
# target_link_libraries(cache-scratch pthread)
|
||||
|
||||
# add_executable(cache-thrash cache-thrash/cache-thrash.cpp)
|
||||
# target_link_libraries(cache-thrash pthread)
|
||||
|
||||
# add_executable(xmalloc-test xmalloc-test/xmalloc-test.c)
|
||||
# target_link_libraries(xmalloc-test pthread)
|
||||
|
||||
# add_executable(malloc-large-old malloc-large/malloc-large-old.cpp)
|
||||
# target_link_libraries(malloc-large-old pthread)
|
||||
|
||||
# add_executable(malloc-large malloc-large/malloc-large.cpp)
|
||||
# target_link_libraries(malloc-large pthread)
|
||||
|
||||
# add_executable(mstress mstress/mstress.c)
|
||||
# target_link_libraries(mstress pthread)
|
||||
|
||||
# add_executable(mleak mleak/mleak.c)
|
||||
# target_link_libraries(mleak pthread)
|
||||
|
||||
# add_executable(rptest rptest/rptest.c rptest/thread.c rptest/timer.c)
|
||||
# target_compile_options(rptest PRIVATE -fpermissive)
|
||||
# target_include_directories(rptest PRIVATE rptest)
|
||||
# target_link_libraries(rptest pthread m)
|
||||
|
||||
# add_executable(glibc-simple glibc-bench/bench-malloc-simple.c)
|
||||
# target_link_libraries(glibc-simple pthread)
|
||||
|
||||
# add_executable(glibc-thread glibc-bench/bench-malloc-thread.c)
|
||||
# target_link_libraries(glibc-thread pthread)
|
||||
|
||||
#
|
||||
116
benchmarks/benchmarks/espresso/CMakeLists.txt
Normal file
116
benchmarks/benchmarks/espresso/CMakeLists.txt
Normal file
@@ -0,0 +1,116 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(mimalloc-bench CXX C)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "No build type selected, default to *** Release ***")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
FUNCTION(PREPEND var prefix)
|
||||
SET(listVar "")
|
||||
FOREACH(f ${ARGN})
|
||||
LIST(APPEND listVar "${prefix}/${f}")
|
||||
ENDFOREACH(f)
|
||||
SET(${var} "${listVar}" PARENT_SCOPE)
|
||||
ENDFUNCTION(PREPEND)
|
||||
|
||||
# set(cfrac_sources
|
||||
# cfrac.c
|
||||
# pops.c pconst.c pio.c
|
||||
# pabs.c pneg.c pcmp.c podd.c phalf.c
|
||||
# padd.c psub.c pmul.c pdivmod.c psqrt.c ppowmod.c
|
||||
# atop.c ptoa.c itop.c utop.c ptou.c errorp.c
|
||||
# pfloat.c pidiv.c pimod.c picmp.c
|
||||
# primes.c pcfrac.c pgcd.c)
|
||||
# PREPEND(cfrac_sources cfrac/ ${cfrac_sources})
|
||||
|
||||
set(espresso_sources
|
||||
cofactor.c cols.c compl.c contain.c cubestr.c cvrin.c cvrm.c cvrmisc.c cvrout.c
|
||||
dominate.c equiv.c espresso.c essen.c exact.c expand.c gasp.c getopt.c gimpel.c
|
||||
globals.c hack.c indep.c irred.c main.c map.c matrix.c mincov.c opo.c pair.c part.c
|
||||
primes.c reduce.c rows.c set.c setc.c sharp.c sminterf.c solution.c sparse.c unate.c
|
||||
utility.c verify.c)
|
||||
PREPEND(espresso_sources . ${espresso_sources})
|
||||
|
||||
# set(barnes_sources
|
||||
# code.c code_io.c load.c grav.c getparam.c util.c)
|
||||
# PREPEND(barnes_sources barnes/ ${barnes_sources})
|
||||
|
||||
# turn off warnings..
|
||||
message(STATUS "${CMAKE_C_COMPILER_ID}")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
|
||||
set(FLAGS " -w -Wno-implicit-function-declaration -Wno-implicit-int -Wno-int-conversion -Wno-return-mismatch -Wno-incompatible-pointer-types -mabi=purecap-benchmark")
|
||||
string(APPEND CMAKE_C_FLAGS ${FLAGS})
|
||||
string(APPEND CMAKE_CXX_FLAGS ${FLAGS})
|
||||
endif()
|
||||
|
||||
# add_executable(cfrac ${cfrac_sources})
|
||||
# target_compile_options(cfrac PRIVATE $<$<C_COMPILER_ID:GNU>:-std=gnu89>)
|
||||
# target_compile_definitions(cfrac PRIVATE NOMEMOPT=1)
|
||||
# target_link_libraries(cfrac m)
|
||||
|
||||
add_executable(espresso ${espresso_sources})
|
||||
target_compile_options(espresso PRIVATE $<$<C_COMPILER_ID:GNU>:-std=gnu89>)
|
||||
target_link_libraries(espresso m)
|
||||
|
||||
# add_executable(barnes ${barnes_sources})
|
||||
# target_link_libraries(barnes m)
|
||||
|
||||
# add_executable(larson larson/larson.cpp)
|
||||
# target_compile_options(larson PRIVATE -Wno-unused-result)
|
||||
# target_compile_definitions(larson PRIVATE CPP=1)
|
||||
# target_link_libraries(larson pthread)
|
||||
|
||||
# add_executable(larson-sized larson/larson.cpp)
|
||||
# target_compile_options(larson-sized PRIVATE -Wno-unused-result -fsized-deallocation)
|
||||
# target_compile_definitions(larson-sized PRIVATE CPP=1 SIZED=1)
|
||||
# target_link_libraries(larson-sized pthread)
|
||||
|
||||
# add_executable(alloc-test alloc-test/test_common.cpp alloc-test/allocator_tester.cpp)
|
||||
# target_compile_definitions(alloc-test PRIVATE BENCH=4)
|
||||
# target_link_libraries(alloc-test pthread)
|
||||
|
||||
# if(NOT APPLE)
|
||||
# add_executable(sh6bench shbench/sh6bench-new.c)
|
||||
# target_compile_definitions(sh6bench PRIVATE BENCH=1 SYS_MULTI_THREAD=1)
|
||||
# target_link_libraries(sh6bench pthread)
|
||||
|
||||
# add_executable(sh8bench shbench/sh8bench-new.c)
|
||||
# target_compile_definitions(sh8bench PRIVATE BENCH=1 SYS_MULTI_THREAD=1)
|
||||
# target_link_libraries(sh8bench pthread)
|
||||
# endif()
|
||||
|
||||
# add_executable(cache-scratch cache-scratch/cache-scratch.cpp)
|
||||
# target_link_libraries(cache-scratch pthread)
|
||||
|
||||
# add_executable(cache-thrash cache-thrash/cache-thrash.cpp)
|
||||
# target_link_libraries(cache-thrash pthread)
|
||||
|
||||
# add_executable(xmalloc-test xmalloc-test/xmalloc-test.c)
|
||||
# target_link_libraries(xmalloc-test pthread)
|
||||
|
||||
# add_executable(malloc-large-old malloc-large/malloc-large-old.cpp)
|
||||
# target_link_libraries(malloc-large-old pthread)
|
||||
|
||||
# add_executable(malloc-large malloc-large/malloc-large.cpp)
|
||||
# target_link_libraries(malloc-large pthread)
|
||||
|
||||
# add_executable(mstress mstress/mstress.c)
|
||||
# target_link_libraries(mstress pthread)
|
||||
|
||||
# add_executable(mleak mleak/mleak.c)
|
||||
# target_link_libraries(mleak pthread)
|
||||
|
||||
# add_executable(rptest rptest/rptest.c rptest/thread.c rptest/timer.c)
|
||||
# target_compile_options(rptest PRIVATE -fpermissive)
|
||||
# target_include_directories(rptest PRIVATE rptest)
|
||||
# target_link_libraries(rptest pthread m)
|
||||
|
||||
# add_executable(glibc-simple glibc-bench/bench-malloc-simple.c)
|
||||
# target_link_libraries(glibc-simple pthread)
|
||||
|
||||
# add_executable(glibc-thread glibc-bench/bench-malloc-thread.c)
|
||||
# target_link_libraries(glibc-thread pthread)
|
||||
|
||||
#
|
||||
@@ -39,8 +39,8 @@
|
||||
|
||||
#include "coz.h"
|
||||
|
||||
#define malloc MALLOC
|
||||
#define free FREE
|
||||
// #define malloc MALLOCCHERI
|
||||
// #define free FREECHERI
|
||||
|
||||
#define DEF_NUM_POINTS 150000
|
||||
#define DEF_NUM_MEANS 100
|
||||
@@ -270,8 +270,8 @@ int main(int argc, char **argv)
|
||||
// Extra code snippet added
|
||||
// printf("Initial alloc called\n");
|
||||
//INITAlloc();
|
||||
//INITREGULARALLOC();
|
||||
init_malloc();
|
||||
// INITREGULARALLOC();
|
||||
// init_malloc();
|
||||
|
||||
int num_procs, curr_point;
|
||||
int i;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
sh build.sh
|
||||
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-350000.txt ./kmeans-pthread.out -d 40 -c 100 -p 350000 -s 1000 > kmeans-bounds-regular-350000-out.txt
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-300000.txt ./kmeans-pthread.out -d 40 -c 100 -p 300000 -s 1000 > kmeans-bounds-regular-300000-out.txt
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-250000.txt ./kmeans-pthread.out -d 40 -c 100 -p 250000 -s 1000 > kmeans-bounds-regular-250000-out.txt
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-200000.txt ./kmeans-pthread.out -d 40 -c 100 -p 200000 -s 1000 > kmeans-bounds-regular-200000-out.txt
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-150000.txt ./kmeans-pthread.out -d 40 -c 100 -p 150000 -s 1000 > kmeans-bounds-regular-150000-out.txt
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-100000.txt ./kmeans-pthread.out -d 40 -c 100 -p 100000 -s 1000 > kmeans-bounds-regular-100000-out.txt
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-10000.txt ./kmeans-pthread.out -d 40 -c 100 -p 10000 -s 1000 > kmeans-bounds-regular-10000-out.txt
|
||||
time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-1000.txt ./kmeans-pthread.out -d 40 -c 100 -p 1000 -s 1000 > kmeans-bounds-regular-1000-out.txt
|
||||
# time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-10000.txt ./kmeans-pthread.out -d 40 -c 100 -p 10000 -s 1000 > kmeans-bounds-regular-10000-out.txt
|
||||
# time pmcstat -d -w 1 -p l1d_tlb_rd -p l2d_tlb_rd -p l1d_tlb_refill -p cpu_cycles -p dtlb_walk -p stall_backend -p ll_cache_miss_rd -o kmeans-regular-alloc-1000.txt ./kmeans-pthread.out -d 40 -c 100 -p 1000 -s 1000 > kmeans-bounds-regular-1000-out.txt
|
||||
@@ -1,177 +1,177 @@
|
||||
/* Copyright (C) 2023. Shivashish Das. Licensed under the MIT License.*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
// /* Copyright (C) 2023. Shivashish Das. Licensed under the MIT License.*/
|
||||
// #include <stdint.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <stdio.h>
|
||||
// #include <string.h>
|
||||
// #include <time.h>
|
||||
|
||||
// source: https://www.reddit.com/r/C_Programming/comments/1bt8dyz/github_dasshivamalloc_a_simple_memory_allocator/
|
||||
// // source: https://www.reddit.com/r/C_Programming/comments/1bt8dyz/github_dasshivamalloc_a_simple_memory_allocator/
|
||||
|
||||
// #include "alloc.h"
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
/* This is a simple memory allocator meant for use in single threaded applications.
|
||||
First we get memory from the system allocator which is defined by the pool size
|
||||
Larger the pool size, more is the amount you can allocate before running out of memory.
|
||||
On linux, mmap() is used for memory allocation while on windows good old calloc() is used as the system allocator
|
||||
// // #include "alloc.h"
|
||||
// #ifndef _MSC_VER
|
||||
// #include <sys/mman.h>
|
||||
// #endif
|
||||
// /* This is a simple memory allocator meant for use in single threaded applications.
|
||||
// First we get memory from the system allocator which is defined by the pool size
|
||||
// Larger the pool size, more is the amount you can allocate before running out of memory.
|
||||
// On linux, mmap() is used for memory allocation while on windows good old calloc() is used as the system allocator
|
||||
|
||||
Some basic definitions:
|
||||
Block - A memory region always of size 16 bytes. This is the basic unit of allocation
|
||||
All allocations are made in multiples of blocks. If any allocation request is not a multiple of 16 bytes, we return memory of a size
|
||||
that is the closest multiple to 16 and greater than the user requested size.
|
||||
// Some basic definitions:
|
||||
// Block - A memory region always of size 16 bytes. This is the basic unit of allocation
|
||||
// All allocations are made in multiples of blocks. If any allocation request is not a multiple of 16 bytes, we return memory of a size
|
||||
// that is the closest multiple to 16 and greater than the user requested size.
|
||||
|
||||
Metadata blocks - For every allocation we allocate two extra blocks. These two blocks hold data about the allocation itself
|
||||
and serve to prevent buffer overflows too. Check the comment in alloc() to find out more. For example suppose that if the user asks for 80 bytes
|
||||
i.e 80 / 16 = 5 blocks, we will allocate 7 blocks but the pointer passed to the user will point to the seconf block so the user is unable to access
|
||||
these blocks. They do sound like a waste of some bytes but help provide protection from buffer overflows
|
||||
// Metadata blocks - For every allocation we allocate two extra blocks. These two blocks hold data about the allocation itself
|
||||
// and serve to prevent buffer overflows too. Check the comment in alloc() to find out more. For example suppose that if the user asks for 80 bytes
|
||||
// i.e 80 / 16 = 5 blocks, we will allocate 7 blocks but the pointer passed to the user will point to the seconf block so the user is unable to access
|
||||
// these blocks. They do sound like a waste of some bytes but help provide protection from buffer overflows
|
||||
|
||||
Posioning - This means that user code has overflown the buffer it was allocated. All memory allocated by alloc() is now invalid
|
||||
However this may also be caused by the user simply passing an invalid pointer to us i.e a pointer allocated by some other allocator etc.
|
||||
In this case the user can clear the poisoned state by calling clear_posion() but be absolutely sure as a user about this before doing so
|
||||
*/
|
||||
static uint8_t* mem = 0;
|
||||
static uint8_t* bitmap = 0;
|
||||
static uint64_t blocks = 0;
|
||||
static uint8_t poison = 0;
|
||||
// Posioning - This means that user code has overflown the buffer it was allocated. All memory allocated by alloc() is now invalid
|
||||
// However this may also be caused by the user simply passing an invalid pointer to us i.e a pointer allocated by some other allocator etc.
|
||||
// In this case the user can clear the poisoned state by calling clear_posion() but be absolutely sure as a user about this before doing so
|
||||
// */
|
||||
// static uint8_t* mem = 0;
|
||||
// static uint8_t* bitmap = 0;
|
||||
// static uint64_t blocks = 0;
|
||||
// static uint8_t poison = 0;
|
||||
|
||||
// Always call this before anything else.
|
||||
void alloc_init(uint64_t pool) {
|
||||
if (pool % 16 != 0) {
|
||||
int rem = pool % 16;
|
||||
pool += (16 - rem);
|
||||
}
|
||||
// // Always call this before anything else.
|
||||
// void alloc_init(uint64_t pool) {
|
||||
// if (pool % 16 != 0) {
|
||||
// int rem = pool % 16;
|
||||
// pool += (16 - rem);
|
||||
// }
|
||||
|
||||
#ifndef _MSC_VER
|
||||
mem = mmap(0, pool, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (mem == MAP_FAILED) {
|
||||
fprintf(stderr, "alloc_init(): could not allocate heap\n");
|
||||
perror("mmap");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
mem = calloc(pool, 1);
|
||||
if (!mem) {
|
||||
fprintf(stderr, "alloc_init(): could not allocate heap\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
// Each bitmap entry can represent 8 blocks and each block is 16 bytes
|
||||
// So space representable in one uint8_t is 16 * 8 = 128 bytes
|
||||
uint64_t sz = pool / 128;
|
||||
if (sz == 0)
|
||||
sz = 1; // allocate at least one to keep track of small pools
|
||||
// #ifndef _MSC_VER
|
||||
// mem = mmap(0, pool, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
// if (mem == MAP_FAILED) {
|
||||
// fprintf(stderr, "alloc_init(): could not allocate heap\n");
|
||||
// perror("mmap");
|
||||
// return;
|
||||
// }
|
||||
// #else
|
||||
// mem = calloc(pool, 1);
|
||||
// if (!mem) {
|
||||
// fprintf(stderr, "alloc_init(): could not allocate heap\n");
|
||||
// exit(1);
|
||||
// }
|
||||
// #endif
|
||||
// // Each bitmap entry can represent 8 blocks and each block is 16 bytes
|
||||
// // So space representable in one uint8_t is 16 * 8 = 128 bytes
|
||||
// uint64_t sz = pool / 128;
|
||||
// if (sz == 0)
|
||||
// sz = 1; // allocate at least one to keep track of small pools
|
||||
|
||||
#ifndef _MSC_VER
|
||||
bitmap = mmap(0, sz , PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (bitmap == MAP_FAILED) {
|
||||
fprintf(stderr, "alloc_init(): could not allocate bitmap");
|
||||
munmap(mem, pool);
|
||||
}
|
||||
#else
|
||||
bitmap = calloc(sz, 1);
|
||||
if (!bitmap) {
|
||||
fprintf(stderr, "alloc_init(): could not allocate bitmap\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
// Zero the entire bitmap
|
||||
memset(bitmap, 0, sz);
|
||||
blocks = pool / 16;
|
||||
}
|
||||
// #ifndef _MSC_VER
|
||||
// bitmap = mmap(0, sz , PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
// if (bitmap == MAP_FAILED) {
|
||||
// fprintf(stderr, "alloc_init(): could not allocate bitmap");
|
||||
// munmap(mem, pool);
|
||||
// }
|
||||
// #else
|
||||
// bitmap = calloc(sz, 1);
|
||||
// if (!bitmap) {
|
||||
// fprintf(stderr, "alloc_init(): could not allocate bitmap\n");
|
||||
// exit(1);
|
||||
// }
|
||||
// #endif
|
||||
// // Zero the entire bitmap
|
||||
// memset(bitmap, 0, sz);
|
||||
// blocks = pool / 16;
|
||||
// }
|
||||
|
||||
#define IS_FREE(blkid) (bitmap[blkid / 8] & (((uint8_t)1) << blkid)) == 0
|
||||
#define MARK(blkid) (bitmap[blkid / 8] ^= ((((uint8_t)1) << blkid) - 1))
|
||||
// #define IS_FREE(blkid) (bitmap[blkid / 8] & (((uint8_t)1) << blkid)) == 0
|
||||
// #define MARK(blkid) (bitmap[blkid / 8] ^= ((((uint8_t)1) << blkid) - 1))
|
||||
|
||||
// Allocate sz bytes of memory. Caution: May allocate upto 15 bytes more than sz
|
||||
void* alloc(uint64_t sz) {
|
||||
if (sz % 16 != 0) {
|
||||
int rem = sz % 16;
|
||||
sz += (16 - rem);
|
||||
}
|
||||
// Allocate two extra blocks
|
||||
// First will be allocated at just behind the first user accessible block
|
||||
// This block will have the number of blocks allocated and a randomly generated magic number each 8 bytes long
|
||||
// The last block has the "magic number" present in the first block
|
||||
// If this magic number gets modified then when free() tries to free the memory
|
||||
// Buffer overruns will be caught and this allocator gets poisoned i.e it can no longer allocate memory
|
||||
// This is because all blocks are laid out sequentially and if the user overruns the blocks allocated
|
||||
// Then the user may have overwritten the contents of other blocks and it is not possible to estimate the damage caused
|
||||
// and data corrupted. All pointers to blocks allocated immediately become invalid and free() posions the allocator
|
||||
// This helps catch buffer overflows early on
|
||||
uint64_t blk = (sz / 16) + 2;
|
||||
// // Allocate sz bytes of memory. Caution: May allocate upto 15 bytes more than sz
|
||||
// void* alloc(uint64_t sz) {
|
||||
// if (sz % 16 != 0) {
|
||||
// int rem = sz % 16;
|
||||
// sz += (16 - rem);
|
||||
// }
|
||||
// // Allocate two extra blocks
|
||||
// // First will be allocated at just behind the first user accessible block
|
||||
// // This block will have the number of blocks allocated and a randomly generated magic number each 8 bytes long
|
||||
// // The last block has the "magic number" present in the first block
|
||||
// // If this magic number gets modified then when free() tries to free the memory
|
||||
// // Buffer overruns will be caught and this allocator gets poisoned i.e it can no longer allocate memory
|
||||
// // This is because all blocks are laid out sequentially and if the user overruns the blocks allocated
|
||||
// // Then the user may have overwritten the contents of other blocks and it is not possible to estimate the damage caused
|
||||
// // and data corrupted. All pointers to blocks allocated immediately become invalid and free() posions the allocator
|
||||
// // This helps catch buffer overflows early on
|
||||
// uint64_t blk = (sz / 16) + 2;
|
||||
|
||||
// if we are posioned, all allocation requests will fail
|
||||
if (poison)
|
||||
return 0;
|
||||
// Loop through the entire bitmap. If a free block is found, check if there are at least blk free blocks after it.
|
||||
// If such a contigious group of blocks is found, take appropriate actions and return to user
|
||||
// Otherwise we have ran out of memory so inform the user about it
|
||||
for (uint64_t i = 0; i < blocks; i++) {
|
||||
if (IS_FREE(i)) {
|
||||
// Check for contigious free blocks
|
||||
for (uint64_t j = i; j < (i + blk); j++) {
|
||||
if (!IS_FREE(j))
|
||||
goto next;
|
||||
}
|
||||
// // if we are posioned, all allocation requests will fail
|
||||
// if (poison)
|
||||
// return 0;
|
||||
// // Loop through the entire bitmap. If a free block is found, check if there are at least blk free blocks after it.
|
||||
// // If such a contigious group of blocks is found, take appropriate actions and return to user
|
||||
// // Otherwise we have ran out of memory so inform the user about it
|
||||
// for (uint64_t i = 0; i < blocks; i++) {
|
||||
// if (IS_FREE(i)) {
|
||||
// // Check for contigious free blocks
|
||||
// for (uint64_t j = i; j < (i + blk); j++) {
|
||||
// if (!IS_FREE(j))
|
||||
// goto next;
|
||||
// }
|
||||
|
||||
// Mark all free blocks
|
||||
for (uint64_t j = i; j < (i + blk + 1); j++) {
|
||||
MARK(j);
|
||||
}
|
||||
uint64_t* ptr = mem + (i * 16);
|
||||
*ptr = blk;
|
||||
// // Mark all free blocks
|
||||
// for (uint64_t j = i; j < (i + blk + 1); j++) {
|
||||
// MARK(j);
|
||||
// }
|
||||
// uint64_t* ptr = mem + (i * 16);
|
||||
// *ptr = blk;
|
||||
|
||||
// I needed a number which was large enough to occupy 8 bytes so rand() is not enough as in most cases RAND_MAX is only USHORT_MAX
|
||||
// Instead use time() which returns a 64 bit value and is almost guaranteed to be unique on every call to alloc()
|
||||
uint64_t magic = time(0);
|
||||
*(ptr + 1) = magic;
|
||||
// // I needed a number which was large enough to occupy 8 bytes so rand() is not enough as in most cases RAND_MAX is only USHORT_MAX
|
||||
// // Instead use time() which returns a 64 bit value and is almost guaranteed to be unique on every call to alloc()
|
||||
// uint64_t magic = time(0);
|
||||
// *(ptr + 1) = magic;
|
||||
|
||||
// Store a magic number in the last block. For the reason see free_mem()
|
||||
ptr = mem + (i * 16) + ((blk - 1) * 16);
|
||||
*ptr = magic;
|
||||
*(ptr + 1) = magic;
|
||||
// Return the user a pointer which points to the region just above our metadata block
|
||||
return mem + ((i + 1) * 16);
|
||||
}
|
||||
next:
|
||||
}
|
||||
fprintf(stderr, "Pool has been exhausted...Cannot allocate more memory");
|
||||
return 0;
|
||||
}
|
||||
// // Store a magic number in the last block. For the reason see free_mem()
|
||||
// ptr = mem + (i * 16) + ((blk - 1) * 16);
|
||||
// *ptr = magic;
|
||||
// *(ptr + 1) = magic;
|
||||
// // Return the user a pointer which points to the region just above our metadata block
|
||||
// return mem + ((i + 1) * 16);
|
||||
// }
|
||||
// next:
|
||||
// }
|
||||
// fprintf(stderr, "Pool has been exhausted...Cannot allocate more memory");
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// Frees memory allocated by alloc()
|
||||
void free_mem(void* data) {
|
||||
// First get the number of blocks allocated and magic from the metadata block (i.e the block right behind what alloc() returned)
|
||||
uint64_t* ptr = data;
|
||||
ptr -= 2;
|
||||
uint64_t blk = *ptr;
|
||||
ptr++;
|
||||
uint64_t magic = *ptr;
|
||||
// // Frees memory allocated by alloc()
|
||||
// void free_mem(void* data) {
|
||||
// // First get the number of blocks allocated and magic from the metadata block (i.e the block right behind what alloc() returned)
|
||||
// uint64_t* ptr = data;
|
||||
// ptr -= 2;
|
||||
// uint64_t blk = *ptr;
|
||||
// ptr++;
|
||||
// uint64_t magic = *ptr;
|
||||
|
||||
// The magic is stored in the last block of the allocation
|
||||
// Compare the two magic values
|
||||
// If they are equal, this memory block was allocated by us and we can free this
|
||||
// Otherwise the buffer has been overflown which has overwritten the magic number or this was not allocated by alloc() and is not ours to deal with
|
||||
ptr = data + (blk - 2) * 16;
|
||||
if (magic != *ptr) {
|
||||
// If the buffer has overflown then mark this allocator posioned.
|
||||
// You may change the poison back to 0 in your code but be careful and do this only if you know that the buffer was not overrun
|
||||
fprintf(stderr, "Invalid pointer or buffer overrun detected..Poisoning ourself");
|
||||
poison = 1;
|
||||
return;
|
||||
}
|
||||
uint64_t offset = ((uint8_t*) data) - mem;
|
||||
offset -= 16;
|
||||
offset /= 16;
|
||||
// // The magic is stored in the last block of the allocation
|
||||
// // Compare the two magic values
|
||||
// // If they are equal, this memory block was allocated by us and we can free this
|
||||
// // Otherwise the buffer has been overflown which has overwritten the magic number or this was not allocated by alloc() and is not ours to deal with
|
||||
// ptr = data + (blk - 2) * 16;
|
||||
// if (magic != *ptr) {
|
||||
// // If the buffer has overflown then mark this allocator posioned.
|
||||
// // You may change the poison back to 0 in your code but be careful and do this only if you know that the buffer was not overrun
|
||||
// fprintf(stderr, "Invalid pointer or buffer overrun detected..Poisoning ourself");
|
||||
// poison = 1;
|
||||
// return;
|
||||
// }
|
||||
// uint64_t offset = ((uint8_t*) data) - mem;
|
||||
// offset -= 16;
|
||||
// offset /= 16;
|
||||
|
||||
// Clear all bits representing this block so next call to alloc() can use this
|
||||
for (uint64_t j = offset; j < offset + blk + 1; j++) {
|
||||
MARK(j);
|
||||
}
|
||||
}
|
||||
// // Clear all bits representing this block so next call to alloc() can use this
|
||||
// for (uint64_t j = offset; j < offset + blk + 1; j++) {
|
||||
// MARK(j);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Do not call this unless you are absolutely sure about the cause of poisoning
|
||||
void clear_posion() {
|
||||
poison = 0;
|
||||
}
|
||||
// // Do not call this unless you are absolutely sure about the cause of poisoning
|
||||
// void clear_posion() {
|
||||
// poison = 0;
|
||||
// }
|
||||
@@ -54,29 +54,29 @@
|
||||
#define MAXPAGESIZES 2
|
||||
|
||||
|
||||
init_malloc(void) {
|
||||
// Init malloc implementation
|
||||
//INITREGULARALLOC();
|
||||
// init_malloc(void) {
|
||||
// // Init malloc implementation
|
||||
// INITREGULARALLOC();
|
||||
|
||||
// init_alloc(100,100000);
|
||||
// brm_init();
|
||||
alloc_init(104857632);
|
||||
}
|
||||
// // init_alloc(100,100000);
|
||||
// // brm_init();
|
||||
// //alloc_init(104857632);
|
||||
// }
|
||||
|
||||
void* MALLOC(size_t sz) {
|
||||
// malloc implementation
|
||||
//return MALLOCCHERI(sz);
|
||||
// return malloc_buddy(sz);
|
||||
return alloc(sz);
|
||||
// return (void *)alloc_chunk();
|
||||
}
|
||||
// void* MALLOC(size_t sz) {
|
||||
// // malloc implementation
|
||||
// return MALLOCCHERI(sz);
|
||||
// // return malloc_buddy(sz);
|
||||
// // return alloc(sz);
|
||||
// // return (void *)alloc_chunk();
|
||||
// }
|
||||
|
||||
void FREE(void *ptr) {
|
||||
// free implementation
|
||||
//FREECHERI(ptr);
|
||||
// free_chunk(ptr);
|
||||
free_mem(ptr);
|
||||
}
|
||||
// void FREE(void *ptr) {
|
||||
// // free implementation
|
||||
// FREECHERI(ptr);
|
||||
// // free_chunk(ptr);
|
||||
// //free_mem(ptr);
|
||||
// }
|
||||
|
||||
|
||||
//#define TIMING
|
||||
|
||||
@@ -441,7 +441,8 @@ int main(int argc, char* argv[])
|
||||
unsigned long start = microseconds();
|
||||
result += inner_loop(inner_iterations);
|
||||
unsigned long elapsed = microseconds() - start;
|
||||
printf("Richards: iterations=1 runtime: %lu%s\n", elapsed, "us");
|
||||
// printf("Richards: iterations=1 runtime: %lu%s\n", elapsed, "us");
|
||||
print(elapsed);
|
||||
iterations--;
|
||||
}
|
||||
}
|
||||
1
benchmarks/benchmarks/xmalloc-test/build.sh
Normal file
1
benchmarks/benchmarks/xmalloc-test/build.sh
Normal file
@@ -0,0 +1 @@
|
||||
cc -g -Wall -o main.out -mabi=purecap-benchmark -lpthread xmalloc-test.c
|
||||
Reference in New Issue
Block a user