UMAP-APPS¶
This repository contains applications that use the umap library to manage large regions of memory for them.
- Take a look at our Getting Started guide for all you need to get up and running.
Getting Started¶
Dependencies¶
At a minimum, the programs under umap-apps depend cmake 3.5.1 or greater and upon umap being installed.
Follow the instructions for installing umap from the umap repository located here.
Umap-apps Build and Installation¶
Once the prerequisites are taken care of, the following lines should get you up and running:
$ git clone https://github.com/LLNL/umap-apps.git
$ mkdir build && cd build
$ cmake -DUMAP_INSTALL_PATH="<path to where umap is installed>" ../umap-apps
$ make
By default, umap-apps will build a Release type build and will use the system defined directories for installation. To specify different build types or specify alternate installation paths, see the Advanced Configuration.
Should you wish to also install the applications in their respective installation directories, type:
$ make install
Umap-apps installs files to the lib
, include
and bin
directories
of the CMAKE_INSTALL_PREFIX
.
Advanced Configuration¶
Listed below are the umap-specific options which may be used when configuring your build directory with cmake. Some CMake-specific options have also been added to show how to make additional changes to the build configuration.
cmake -DUMAP_INSTALL_PATH="<path to where umap is installed>"
Here is a summary of the configuration options, their default value, and meaning:
Variable Default Meaning UMAP_INSTALL_PATH
not set Location of umap CFITS_LIBRARY_PATH
not set Location of cfitsio library CFITS_INCLUDE_PATH
not set Location of cfitsio include files CMAKE_CXX_COMPILER
not set C++ compiler to use DCMAKE_CC_COMPILER
not set C compiler to use
These arguments are explained in more detail below:
UMAP_INSTALL_PATH
Location of prerequisite umap installation.CFITS_INCLUDE_PATH
andCFITS_LIBRARY_PATH
If these are specified, then the applications that use FITS files as the backing store for umap() will be built.
BFS README¶
## Generate edge list using a R-MAT generator ``` ./rmat_edge_generator/generate_edge_list
-o [out edge list file name (required)]
-s [seed for random number generator; default is 123]
-v [SCALE; The logarithm base two of the number of vertices; default is 17]
-e [#of edges; default is 2^{SCALE} x 16]
-a [initiator parameter A; default is 0.57]
-b [initiator parameter B; default is 0.19]
-c [initiator parameter C; default is 0.19]
-r [if true, scrambles edge IDs; default is true]
-u [if true, generates edges for the both direction; default is true] ```
- As for the initiator parameters,
see [Graph500, 3.2 Detailed Text Description](https://graph500.org/?page_id=12#sec-3_2) for more details.
#### Generate Graph 500 inputs
`
./generate_edge_list -o /mnt/ssd/edge_list -v 20 -e $((2**20*16))
``
This command generates a edge list file (/mnt/ssd/edge_list) which contains the edges of a SCALE 20 graph.
In Graph 500, the number of edges of a graph is #vertives x 16 (16 is called ‘edge factor’).
## Ingest Edge List (construct CSR graph)
`
./ingest_edge_list -g /l/ssd/csr_graph_file /l/ssd/edgelist1 /l/ssd/edgelist2
`
- Load edge data from files /l/ssd/edgelist1 and /l/ssd/edgelist2 (you can specify an arbitrary number of files).
A CSR graph is constructed in /l/ssd/csr_graph_file. * Each line of input files must be a pair of source and destination vertex IDs (unsigned 64bit number). * This program treats inputs as a directed graph, that is, it does not ingest edges for both directions. * This is a multi-threads (OpenMP) program. You can control the number of threads using the environment variable OMP_NUM_THREADS. * As for real-world datasets, [SNAP Datasets](http://snap.stanford.edu/data/index.html) is popular in the graph processing community. Please note that some datasets in SNAP are a little different. For example, the first line is a comment; you have to delete the line before running this program.
## Run BFS
`
./run_bfs -n \[#of vertices\] -m \[#of edges\] -g \[/path/to/graph_file\]
`
- You can get #of vertices and #of edges by running ingest_edge_list.
- This is a multi-threads (OpenMP) program.
You can control the number of threads using the environment variable OMP_NUM_THREADS.
API¶
Class Hierarchy¶
-
- Namespace median
- Template Struct cube_t
- Namespace utility
- Namespace utility::umap_fits_file
- Struct Cube
- Struct Tile_Dim
- Struct Tile_File
- Class CfitsStoreFile
- Class Tile
- Struct umt_optstruct_t
- Namespace utility::umap_fits_file
- Struct options_t
- Struct rmat_option_t
- Struct vector_t
- Class beta_distribution
- Class pageiotest
- Class rmat_edge_generator
- Template Class vector_iterator
- Namespace median
File Hierarchy¶
-
- Directory bfs
- Directory generator
- File generate_edge_list.cpp
- File hash.hpp
- File rmat_edge_generator.hpp
- File bfs_kernel.hpp
- File compute_degree_distribution.cpp
- File ingest_edge_list.cpp
- File README.md
- File run_bfs.cpp
- File test_bfs.cpp
- Directory generator
- Directory churn
- File churn.cpp
- File options.cpp
- File options.h
- Directory calculation
- File INSTRUCTION.md
- File run_random_vector.cpp
- File test_median_calculation.cpp
- File torben.hpp
- File utility.hpp
- File vector.hpp
- Directory pfbenchmark
- File nvmebenchmark.cpp
- File pfbenchmark.cpp
- Directory umapcpu
- File umapcpu.cpp
- Directory umapsort
- File umapsort.cpp
- Directory utility
- File bitmap.hpp
- File commandline.hpp
- File file.hpp
- File mmap.hpp
- File time.hpp
- File umap_file.hpp
- File umap_fits_file.hpp
- Directory bfs
Full API¶
Namespaces¶
Namespace chrono¶
Namespace rmat_edge_generator_detail¶
Contents
Namespace std¶
STL namespace.
Namespace utility¶
Contents
Namespaces¶
Classes¶
Functions¶
- Function utility::bitmap_global_pos
- Function utility::bitmap_local_pos
- Function utility::bitmap_size
- Function utility::create_file
- Function utility::elapsed_time_sec()
- Function utility::elapsed_time_sec(const std::chrono::high_resolution_clock::time_point&)
- Function utility::extend_file_size(const int, const size_t)
- Function utility::extend_file_size(const std::string&, const size_t)
- Function utility::extend_file_size_manually
- Function utility::get_bit
- Function utility::get_page_size
- Function utility::map_file
- Function utility::map_file_read_mode
- Function utility::map_file_write_mode
- Function utility::map_in_file
- Function utility::msync
- Function utility::munmap
- Function utility::set_bit
- Function utility::umt_getoptions
- Function utility::umt_getpagesize
- Function utility::unmap_file
- Function utility::usage
Classes and Structs¶
Struct rmat_option_t¶
- Defined in File generate_edge_list.cpp
Struct umt_optstruct_t¶
- Defined in File commandline.hpp
Class rmat_edge_generator¶
- Defined in File rmat_edge_generator.hpp
Class Documentation¶
-
class
rmat_edge_generator
¶ RMAT edge generator, based on Boost Graph’s RMAT generator
Options include scrambling vertices based on a hash funciton, and symmetrizing the list. Generated edges are not sorted. May contain duplicate and self edges.
Public Types
-
typedef uint64_t
vertex_descriptor
¶
-
typedef std::pair<uint64_t, uint64_t>
value_type
¶
-
typedef value_type
edge_type
¶
Public Functions
-
rmat_edge_generator
(uint64_t seed, uint64_t vertex_scale, uint64_t edge_count, double a, double b, double c, double d, bool scramble, bool undirected)¶ seed used to be 5489
-
input_iterator_type
begin
()¶ Returns the begin of the input iterator.
-
input_iterator_type
end
()¶ Returns the end of the input iterator.
-
void
sanity_max_vertex_id
()¶
-
uint64_t
max_vertex_id
()¶
-
size_t
size
()¶
Protected Functions
Protected Attributes
-
const uint64_t
m_seed
¶
-
std::mt19937
m_rng
¶
-
std::uniform_real_distribution
m_dis
¶
-
const uint64_t
m_vertex_scale
¶
-
const uint64_t
m_edge_count
¶
-
const bool
m_scramble
¶
-
const bool
m_undirected
¶
-
const double
m_rmat_a
¶
-
const double
m_rmat_b
¶
-
const double
m_rmat_c
¶
-
const double
m_rmat_d
¶
-
class
input_iterator_type
: public std::iterator<std::input_iterator_tag, edge_type, ptrdiff_t, const edge_type *, const edge_type&>¶ InputIterator class for rmat_edge_generator.
Public Functions
-
input_iterator_type
(rmat_edge_generator *ptr_rmat, uint64_t count)¶
-
input_iterator_type &
operator++
()¶
-
input_iterator_type
operator++
(int)¶
-
bool
is_equal
(const input_iterator_type &_x) const¶
Friends
-
bool
operator==
(const input_iterator_type &x, const input_iterator_type &y)¶ Return true if x and y are both end or not end, or x and y are the same.
-
bool
operator!=
(const input_iterator_type &x, const input_iterator_type &y)¶ Return false if x and y are both end or not end, or x and y are the same.
-
-
typedef uint64_t
Class rmat_edge_generator::input_iterator_type¶
- Defined in File rmat_edge_generator.hpp
Nested Relationships¶
This class is a nested type of Class rmat_edge_generator.
Inheritance Relationships¶
public std::iterator< std::input_iterator_tag, edge_type, ptrdiff_t, const edge_type *, const edge_type & >
Class Documentation¶
-
class
input_iterator_type
: public std::iterator<std::input_iterator_tag, edge_type, ptrdiff_t, const edge_type *, const edge_type&> InputIterator class for rmat_edge_generator.
Public Functions
-
input_iterator_type
(rmat_edge_generator *ptr_rmat, uint64_t count)
-
const edge_type &
operator*
() const
-
input_iterator_type &
operator++
()
-
input_iterator_type
operator++
(int)¶
-
edge_type *
operator->
()
-
bool
is_equal
(const input_iterator_type &_x) const
Friends
-
bool
operator==
(const input_iterator_type &x, const input_iterator_type &y) Return true if x and y are both end or not end, or x and y are the same.
-
bool
operator!=
(const input_iterator_type &x, const input_iterator_type &y) Return false if x and y are both end or not end, or x and y are the same.
-
Template Class vector_iterator¶
- Defined in File vector.hpp
Class Documentation¶
-
template <typename pixel_type>
classvector_iterator
¶ Public Types
-
template<>
usingvalue_type
= pixel_type¶
-
template<>
usingdifference_type
= ssize_t¶
-
template<>
usingiterator_category
= std::random_access_iterator_tag¶
-
template<>
usingpointer
= value_type *¶
-
template<>
usingreference
= value_type&¶
Public Functions
-
vector_iterator
(const median::cube_t<pixel_type> &_cube, const vector_t &_vector, const size_t _start_pos)¶
-
vector_iterator
(const vector_iterator&)¶
-
bool
operator==
(const vector_iterator &other)¶
-
bool
operator!=
(const vector_iterator &other)¶
-
difference_type
operator-
(const vector_iterator &other)¶
-
value_type
operator*
()¶
-
vector_iterator &
operator++
()¶
Public Static Functions
-
static vector_iterator
create_end
(const median::cube_t<pixel_type> &cube, const vector_t &vector)¶
-
template<>
Functions¶
Function bfs::init_bfs¶
- Defined in File bfs_kernel.hpp
Function bfs::run_bfs¶
- Defined in File bfs_kernel.hpp
Function Documentation¶
-
uint16_t
bfs
::
run_bfs
(const size_t num_vertices, const uint64_t *const index, const uint64_t *const edges, uint16_t *const level, uint64_t *visited_filter)¶ BFS kernel. This kernel runs with OpenMP. In order to simplify the implementation of this kernel, some operations are not designed to avoid race conditions as long as they are consistent with the correct status.
- Parameters
num_vertices
: The number of verticesindex
: A pointer of an index arrayedges
: A pointer of an edges arraylevel
: A pointer of level arrayvisited_filter
: A pointer of an bitset for visited filter
Function check_edge_list¶
- Defined in File ingest_edge_list.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “check_edge_list” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function count_level¶
- Defined in File run_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “count_level” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function cpu_setcpu¶
- Defined in File umapcpu.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “cpu_setcpu” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function do_read_modify_write_pages¶
- Defined in File pfbenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “do_read_modify_write_pages” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function do_read_pages(uint64_t)¶
- Defined in File nvmebenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “do_read_pages” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function do_read_pages(uint64_t, uint64_t)¶
- Defined in File pfbenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “do_read_pages” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function do_write_pages(uint64_t)¶
- Defined in File nvmebenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “do_write_pages” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function do_write_pages(uint64_t, uint64_t)¶
- Defined in File pfbenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “do_write_pages” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function find_bfs_root¶
- Defined in File run_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “find_bfs_root” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Template Function get_index¶
- Defined in File vector.hpp
Function getns(void)¶
- Defined in File umapcpu.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “getns” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function getns(void)¶
- Defined in File umapsort.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “getns” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function getoptions(options_t&, int&, char **)¶
- Defined in File options.cpp
Function getoptions(options_t&, int&, char **)¶
- Defined in File options.h
Function ingest_edges¶
- Defined in File ingest_edge_list.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “ingest_edges” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function initdata(uint64_t *, int64_t)¶
- Defined in File umapcpu.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “initdata” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function initdata(uint64_t *, uint64_t)¶
- Defined in File umapsort.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “initdata” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File compute_degree_distribution.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File ingest_edge_list.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File generate_edge_list.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File run_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File test_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File churn.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File run_random_vector.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File test_median_calculation.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File nvmebenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File pfbenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File umapcpu.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function main(int, char **)¶
- Defined in File umapsort.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function map_graph(const size_t, const size_t, const std::string&)¶
- Defined in File run_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “map_graph” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function map_graph(const size_t, const size_t, const std::string&)¶
- Defined in File test_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “map_graph” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function map_in_file¶
- Defined in File umapsort.cpp
Function Documentation¶
-
void *
utility
::
map_in_file
(std::string filename, bool initonly, bool noinit, bool usemmap, uint64_t numbytes)
Template Function median::get_cube_size¶
- Defined in File utility.hpp
Template Function median::get_frame_size¶
- Defined in File utility.hpp
Template Function median::get_index¶
- Defined in File utility.hpp
Template Function median::is_nan¶
- Defined in File utility.hpp
Template Function median::reverse_byte_order¶
- Defined in File utility.hpp
Function parse_options(int, char **, std::string&, std::vector<std::string>&)¶
- Defined in File ingest_edge_list.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “parse_options” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function parse_options(int, char **, rmat_option_t *, std::string *)¶
- Defined in File generate_edge_list.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “parse_options” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function parse_options(int, char **, size_t&, size_t&, std::string&)¶
- Defined in File run_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “parse_options” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function parse_options(int, char **, size_t&, size_t&, std::string&, std::string&)¶
- Defined in File test_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “parse_options” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function print_stats¶
- Defined in File pfbenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “print_stats” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function print_top_median¶
- Defined in File run_random_vector.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “print_top_median” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function read_modify_write_test¶
- Defined in File pfbenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “read_modify_write_test” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function read_pages¶
- Defined in File nvmebenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “read_pages” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function read_test¶
- Defined in File pfbenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “read_test” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function rmat_edge_generator_detail::hash16¶
- Defined in File hash.hpp
Function rmat_edge_generator_detail::hash32¶
- Defined in File hash.hpp
Function rmat_edge_generator_detail::hash_nbits¶
- Defined in File hash.hpp
Function rmat_edge_generator_detail::shifted_n_hash16¶
- Defined in File hash.hpp
Function rmat_edge_generator_detail::shifted_n_hash32¶
- Defined in File hash.hpp
Function shoot_vector¶
- Defined in File run_random_vector.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “shoot_vector” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Template Function torben¶
- Defined in File torben.hpp
Function unmap_file¶
- Defined in File umapsort.cpp
Function Documentation¶
-
void
utility
::
unmap_file
(bool usemmap, uint64_t numbytes, void *region)
Function usage¶
- Defined in File options.cpp
Function Documentation¶
-
static void
utility
::
usage
(char *pname)
Function utility::bitmap_global_pos¶
- Defined in File bitmap.hpp
Function utility::bitmap_local_pos¶
- Defined in File bitmap.hpp
Function utility::bitmap_size¶
- Defined in File bitmap.hpp
Function utility::create_file¶
- Defined in File file.hpp
Function utility::elapsed_time_sec()¶
- Defined in File time.hpp
Function Documentation¶
-
std::chrono::high_resolution_clock::time_point
utility
::
elapsed_time_sec
()
Function utility::elapsed_time_sec(const std::chrono::high_resolution_clock::time_point&)¶
- Defined in File time.hpp
Function utility::extend_file_size(const int, const size_t)¶
- Defined in File file.hpp
Function Documentation¶
-
bool
utility
::
extend_file_size
(const int fd, const size_t file_size)
Function utility::extend_file_size(const std::string&, const size_t)¶
- Defined in File file.hpp
Function utility::extend_file_size_manually¶
- Defined in File file.hpp
Function utility::get_bit¶
- Defined in File bitmap.hpp
Function utility::get_page_size¶
- Defined in File mmap.hpp
Function utility::map_file¶
- Defined in File mmap.hpp
Function Documentation¶
-
void *
utility
::
map_file
(void *const addr, const size_t length, const int protection, const int flags, const int fd, const off_t offset)¶ Maps a file checking errors.
- Return
- On success, returns a pointer to the mapped area. On error, nullptr is returned.
- Parameters
addr
: Same as mmap(2)length
: Same as mmap(2)protection
: Same as mmap(2)flags
: Same as mmap(2)fd
: Same as mmap(2)offset
: Same as mmap(2)
Function utility::map_file_read_mode¶
- Defined in File mmap.hpp
Function Documentation¶
-
std::pair<int, void *>
utility
::
map_file_read_mode
(const std::string &file_name, void *const addr, const size_t length, const off_t offset, const int additional_flags = 0)¶ Maps a file with read mode.
- Return
- On Success, returns a pair of the file descriptor of the file and the starting address for the map. On error, retuns a pair of -1 and nullptr.
- Parameters
file_name
: The name of file to be mappedaddr
: Normally nullptr; if this is not nullptr the kernel takes it as a hint about where to place the mappinglength
: The length of the mapoffset
: The offset in the file
Function utility::map_file_write_mode¶
- Defined in File mmap.hpp
Function Documentation¶
-
std::pair<int, void *>
utility
::
map_file_write_mode
(const std::string &file_name, void *const addr, const size_t length, const off_t offset, const int additional_flags = 0)¶ Maps a file with write mode.
- Return
- On Success, returns a pair of the file descriptor of the file and the starting address for the map. On error, retuns a pair of -1 and nullptr.
- Parameters
file_name
: The name of a file to be mappedaddr
: Normally nullptr; if this is not nullptr the kernel takes it as a hint about where to place the mappinglength
: The length of the mapoffset
: The offset in the file
Function utility::map_in_file¶
- Defined in File umap_file.hpp
Function utility::msync¶
- Defined in File mmap.hpp
Function utility::munmap¶
- Defined in File mmap.hpp
Function utility::set_bit¶
- Defined in File bitmap.hpp
Function utility::umap_fits_file::operator<<¶
- Defined in File umap_fits_file.hpp
Function utility::umap_fits_file::PerFits_alloc_cube¶
- Defined in File umap_fits_file.hpp
Function utility::umap_fits_file::PerFits_free_cube¶
- Defined in File umap_fits_file.hpp
Function utility::umt_getoptions¶
- Defined in File commandline.hpp
Function Documentation¶
-
void
utility
::
umt_getoptions
(utility::umt_optstruct_t *testops, int argc, char *argv[])¶
Function utility::umt_getpagesize¶
- Defined in File commandline.hpp
Function utility::unmap_file¶
- Defined in File umap_file.hpp
Function utility::usage¶
- Defined in File commandline.hpp
Function validate_level¶
- Defined in File test_bfs.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “validate_level” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function validatedata¶
- Defined in File umapsort.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “validatedata” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function write_pages¶
- Defined in File nvmebenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “write_pages” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Function write_test¶
- Defined in File pfbenchmark.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “write_test” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variables¶
Variable bfs::k_infinite_level¶
- Defined in File bfs_kernel.hpp
Variable correct_median¶
- Defined in File test_median_calculation.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “correct_median” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable default_num_random_vector¶
- Defined in File run_random_vector.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “default_num_random_vector” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable fd¶
- Defined in File nvmebenchmark.cpp
Variable Documentation¶
-
int
utility::umap_fits_file::CfitsStoreFile
::
fd
¶
Variable FILENAME¶
- Defined in File options.cpp
Variable Documentation¶
-
char const *
utility
::
FILENAME
= "abc"
Variable g_count¶
- Defined in File churn.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “g_count” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable glb_array¶
- Defined in File pfbenchmark.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “glb_array” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable num_vectors¶
- Defined in File test_median_calculation.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “num_vectors” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable NUMCHURNPAGES¶
- Defined in File options.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “NUMCHURNPAGES” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable NUMCHURNTHREADS¶
- Defined in File options.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “NUMCHURNTHREADS” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable NUMLOADPAGES¶
- Defined in File options.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “NUMLOADPAGES” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable NUMLOADREADERS¶
- Defined in File options.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “NUMLOADREADERS” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable NUMLOADWRITERS¶
- Defined in File options.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “NUMLOADWRITERS” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable options¶
- Defined in File nvmebenchmark.cpp
Variable Documentation¶
-
options_t
pageiotest
::
options
¶
Variable options¶
- Defined in File pfbenchmark.cpp
Variable Documentation¶
-
options_t
pageiotest
::
options
Variable page_step¶
- Defined in File pfbenchmark.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “page_step” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable pages_to_access¶
- Defined in File nvmebenchmark.cpp
Variable Documentation¶
-
uint64_t
utility::umt_optstruct_t
::
pages_to_access
Variable pages_to_access¶
- Defined in File pfbenchmark.cpp
Variable Documentation¶
-
uint64_t
utility::umt_optstruct_t
::
pages_to_access
Variable pagesize¶
- Defined in File nvmebenchmark.cpp
Variable Documentation¶
-
long
pageiotest
::
pagesize
¶
Variable pagesize¶
- Defined in File pfbenchmark.cpp
Variable Documentation¶
-
long
pageiotest
::
pagesize
Variable shuffled_indexes¶
- Defined in File nvmebenchmark.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “shuffled_indexes” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable shuffled_indexes¶
- Defined in File pfbenchmark.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “shuffled_indexes” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable sort_ascending¶
- Defined in File umapsort.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “sort_ascending” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable TESTDURATION¶
- Defined in File options.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “TESTDURATION” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable tmppagebuf¶
- Defined in File nvmebenchmark.cpp
Variable Documentation¶
Warning
doxygenvariable: Cannot find variable “tmppagebuf” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Variable utility::BUFFERSIZE¶
- Defined in File commandline.hpp
Variable utility::DIRNAME¶
- Defined in File commandline.hpp
Variable utility::FILENAME¶
- Defined in File commandline.hpp
Variable utility::NUMPAGES¶
- Defined in File commandline.hpp
Variable utility::NUMTHREADS¶
- Defined in File commandline.hpp
Variable utility::umap_fits_file::Cubes¶
- Defined in File umap_fits_file.hpp
Variable x_intercept¶
- Defined in File test_median_calculation.cpp
Variable x_slope¶
- Defined in File test_median_calculation.cpp
Variable y_intercept¶
- Defined in File test_median_calculation.cpp
Variable y_slope¶
- Defined in File test_median_calculation.cpp
Defines¶
Define handle_error_en¶
- Defined in File umapcpu.cpp
Define Documentation¶
Warning
doxygendefine: Cannot find define “handle_error_en” in doxygen xml output for project “umap-apps” from directory: ../doxygen/xml/
Define MEDIAN_CALCULATION_COLUMN_MAJOR¶
- Defined in File utility.hpp
Typedefs¶
Typedef pixel_type¶
- Defined in File run_random_vector.cpp
Typedef Documentation¶
-
template<>
usingmedian::cube_t<_pixel_type>
::
pixel_type
= _pixel_type
Typedef pixel_type¶
- Defined in File test_median_calculation.cpp
Typedef Documentation¶
-
template<>
usingmedian::cube_t<_pixel_type>
::
pixel_type
= _pixel_type
Directories¶
Directory calculation¶
Directory path: median_calculation
Directory pfbenchmark¶
Directory path: pfbenchmark
Directory utility¶
Directory path: utility
Files¶
File bfs_kernel.hpp¶
↰ Parent directory (bfs
)
Definition (bfs/bfs_kernel.hpp
)¶
↰ Return to documentation for file (bfs/bfs_kernel.hpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef BFS_BFS_KERNEL_HPP
#define BFS_BFS_KERNEL_HPP
#include <iostream>
#include <limits>
#include "../utility/bitmap.hpp"
#include "../utility/mmap.hpp"
namespace bfs {
static const uint16_t k_infinite_level = std::numeric_limits<uint16_t>::max();
/// \brief initialize variables to run BFS
/// \param num_vertices The number of veritces
/// \param level A pointer of level array
/// \param A pointer to an bitset for visited filter
void init_bfs(const size_t num_vertices, uint16_t *const level, uint64_t *visited_filter) {
for (size_t i = 0; i < num_vertices; ++i)
level[i] = k_infinite_level;
for (size_t i = 0; i < utility::bitmap_size(num_vertices); ++i)
visited_filter[i] = 0;
}
/// \brief BFS kernel.
/// This kernel runs with OpenMP.
/// In order to simplify the implementation of this kernel,
/// some operations are not designed to avoid race conditions
/// as long as they are consistent with the correct status.
/// \param num_vertices The number of vertices
/// \param index A pointer of an index array
/// \param edges A pointer of an edges array
/// \param level A pointer of level array
/// \param visited_filter A pointer of an bitset for visited filter
uint16_t run_bfs(const size_t num_vertices,
const uint64_t *const index,
const uint64_t *const edges,
uint16_t *const level,
uint64_t *visited_filter) {
uint16_t current_level = 0;
bool visited_new_vertex = false;
while (true) { /// BFS main loop
/// BFS loop for a single level
/// We assume that the cost of generating threads at every level is negligible
#ifdef _OPENMP
#pragma omp parallel for schedule (dynamic, 1048576)
#endif
for (uint64_t src = 0; src < num_vertices; ++src) { /// BFS loop for each level
if (level[src] != current_level) continue;
for (size_t i = index[src]; i < index[src + 1]; ++i) {
const uint64_t trg = edges[i];
if (!utility::get_bit(visited_filter, trg) && level[trg] == k_infinite_level) {
level[trg] = current_level + 1;
utility::set_bit(visited_filter, trg);
visited_new_vertex = true;
}
}
}
if (!visited_new_vertex) break;
++current_level;
visited_new_vertex = false;
} /// End of BFS main loop
return current_level;
}
}
#endif //BFS_BFS_KERNEL_HPP
Includes¶
../utility/bitmap.hpp
../utility/mmap.hpp
iostream
limits
Included By¶
Namespaces¶
Functions¶
Variables¶
File bitmap.hpp¶
↰ Parent directory (utility
)
Definition (utility/bitmap.hpp
)¶
↰ Return to documentation for file (utility/bitmap.hpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LIB_UTILITY_BITMAP_HPP
#define LIB_UTILITY_BITMAP_HPP
#include <iostream>
namespace utility
{
/// examples
/// input 1 ~ 64 -> return 1; input 65 ~ 128 -> return 2
constexpr size_t bitmap_size(const size_t size)
{
return (size == 0) ? 0 :
(size - 1ULL) / (sizeof(uint64_t) * 8ULL) + 1ULL;
}
/// examples
/// input 0 ~ 63 -> return 0; input 64 ~ 127 -> return 1;
constexpr uint64_t bitmap_global_pos(const uint64_t pos)
{
return (pos >> 6ULL);
}
constexpr uint64_t bitmap_local_pos(const uint64_t pos)
{
return pos & 0x3FULL;
}
bool get_bit(const uint64_t* const bitmap, const uint64_t pos)
{
return bitmap[bitmap_global_pos(pos)] & (0x1ULL << bitmap_local_pos(pos));
}
void set_bit(uint64_t* const bitmap, const uint64_t pos)
{
bitmap[bitmap_global_pos(pos)] |= 0x1ULL << bitmap_local_pos(pos);
}
} // namespace utility
#endif //LIB_UTILITY_BITMAP_HPP
Includes¶
iostream
Namespaces¶
File churn.cpp¶
↰ Parent directory (churn
)
Definition (churn/churn.cpp
)¶
↰ Return to documentation for file (churn/churn.cpp
)
/*
* This file is part of UMAP. For copyright information see the COPYRIGHT file
* in the top level directory, or at
* https://github.com/LLNL/umap/blob/master/COPYRIGHT This program is free
* software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License (as published by the Free Software
* Foundation) version 2.1 dated February 1999. This program is distributed in
* the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the terms and conditions of the GNU Lesser General Public License for
* more details. You should have received a copy of the GNU Lesser General
* Public License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
The idea is that we have a single "Load Page" and a set
of N "Churn Pages" as follows:
+==================================================+
| |
| Read Load Page(s) |
| |
+--------------------------------------------------+
| |
| Write{/Read} Load Page(s) |
| |
+--------------------------------------------------+
| |
| Churn Page #1 |
| |
+--------------------------------------------------+
| |
| Churn Page #... |
| |
+--------------------------------------------------+
| |
| Churn Page #N |
| |
+==================================================+
We then have a smaller page_buffer_size that these pages will be faulted
into and madvised out of via umap().
The LoadPage will have a set of num_load_reader and num_load_writer threads
focussed exclusively on making reads and writes to locations constrained to
the Load Page.
The the Churn Pages will have num_churn_reader threads performing random
byte read accesses across all of the Churn Pages effectively causing the
Load Page to be paged in and out of the smaller Page_Buffer.
*/
#include <iostream>
#include <cassert>
#include <cstdint>
#include <chrono>
#include <thread>
#include <mutex>
#include <vector>
#include <random>
#include <algorithm>
#include <utmpx.h> // sched_getcpu()
#include <omp.h>
#include "umap/umap.h"
#include "options.h"
#include "../utility/commandline.hpp"
#include "../utility/umap_file.hpp"
uint64_t g_count = 0;
using namespace std;
using namespace chrono;
class pageiotest {
public:
pageiotest(int _ac, char** _av): time_to_stop{false}, pagesize{utility::umt_getpagesize()} {
getoptions(options, _ac, _av);
umt_options.usemmap = options.usemmap;
umt_options.filename = options.fn;
umt_options.noinit = options.noinit;
umt_options.initonly = options.initonly;
num_rw_load_pages = num_read_load_pages = options.num_load_pages;
num_churn_pages = options.num_churn_pages;
base_addr = utility::map_in_file(options.fn, options.initonly,
options.noinit, options.usemmap,
(num_churn_pages + num_rw_load_pages + num_read_load_pages) * pagesize);
if ( base_addr == nullptr ) {
exit(1);
}
assert(base_addr != NULL);
read_load_pages = base_addr;
rw_load_pages = (void*)((uint64_t)base_addr + (num_read_load_pages*pagesize));
churn_pages = (void*)((uint64_t)base_addr + ( (num_read_load_pages + num_rw_load_pages) * pagesize));
if ( ! options.noinit ) {
init();
}
cout << "Churn Test:\n\t"
<< options.page_buffer_size << " Pages in page buffer\n\t"
<< num_read_load_pages << " Read Load (focus) pages from " << hex << read_load_pages << " - " << (void*)((char*)read_load_pages+((num_read_load_pages*pagesize)-1)) << dec << "\n\t"
<< num_rw_load_pages << " RW Load (focus) pages from " << hex << rw_load_pages << " - " << (void*)((char*)rw_load_pages+((num_rw_load_pages*pagesize)-1)) << dec << "\n\t"
<< options.num_churn_pages << " Churn pages from " << hex << churn_pages << " - " << (void*)((char*)churn_pages+((options.num_churn_pages*pagesize)-1)) << dec << "\n\t"
<< options.num_churn_threads << " Churn threads\n\t"
<< options.num_load_reader_threads << " Load Reader threads\n\t"
<< options.num_load_writer_threads << " Load Writer threads\n\t"
<< options.fn << " Backing file\n\t"
<< options.testduration << " seconds for test duration.\n\n";
check();
}
~pageiotest( void ) {
utility::unmap_file(umt_options.usemmap,
(options.num_churn_pages + num_rw_load_pages
+ num_read_load_pages) * pagesize, base_addr);
}
void start( void ) {
if (options.initonly)
return;
for (uint64_t t = 0; t < options.num_load_reader_threads; ++t)
load_readers.push_back(new thread{&pageiotest::load_read, this, t});
for (uint64_t t = 0; t < options.num_load_reader_threads; ++t)
load_rw_readers.push_back(new thread{&pageiotest::load_rw_read, this, t});
for (uint64_t t = 0; t < options.num_load_writer_threads && t < 1; ++t)
load_rw_writers.push_back(new thread{&pageiotest::load_rw_write, this});
for (uint64_t t = 0; t < options.num_churn_threads; ++t)
churn_readers.push_back(new thread{&pageiotest::churn, this, t});
}
void run( void ) {
if (options.initonly)
return;
this_thread::sleep_for(seconds(options.testduration));
}
void stop( void ) {
time_to_stop = true;
for (auto i : load_readers)
i->join();
for (auto i : load_rw_readers)
i->join();
for (auto i : load_rw_writers)
i->join();
for (auto i : churn_readers)
i->join();
}
private:
bool time_to_stop;
utility::umt_optstruct_t umt_options;
options_t options;
long pagesize;
void* base_addr;
void* read_load_pages;
void* rw_load_pages;
void* churn_pages;
vector<thread*> load_readers;
vector<thread*> load_rw_readers;
vector<thread*> load_rw_writers;
vector<thread*> churn_readers;
uint64_t num_churn_pages;
uint64_t num_read_load_pages;
uint64_t num_rw_load_pages;
void check() {
cout << "Checking churn load pages\n";
{
uint64_t* p = (uint64_t*)churn_pages;
for (uint64_t i = 0; i < num_churn_pages * (pagesize/sizeof(*p)); i += (pagesize/sizeof(*p)))
if (p[i] != i) {
cerr << "check(CHURN): *(uint64_t*)" << &p[i] << "=" << p[i] << " != " << (unsigned long long)i << endl;
exit(1);
}
}
cout << "Checking read load pages\n";
{
uint64_t* p = (uint64_t*)(uint64_t)read_load_pages;
for (uint64_t i = 0; i < num_read_load_pages * (pagesize/sizeof(*p)); ++i)
if (p[i] != i) {
cerr << "check(READER): *(uint64_t*)" << &p[i] << "=" << p[i] << " != " << (unsigned long long)i << endl;
exit(1);
}
}
cerr << "Check Complete\n";
}
void init() {
cout << "Initializing churn pages\n";
{
uint64_t* p = (uint64_t*)churn_pages;
#pragma omp parallel for
for (uint64_t i = 0; i < num_churn_pages * (pagesize/sizeof(*p)); ++i)
p[i] = i;
}
cout << "Initializing read load pages pages\n";
{
uint64_t* p = (uint64_t*)(uint64_t)read_load_pages;
#pragma omp parallel for
for (uint64_t i = 0; i < num_read_load_pages * (pagesize/sizeof(*p)); ++i)
p[i] = i;
}
cout << "Initializing rw load pages pages\n";
{
uint64_t* p = (uint64_t*)(uint64_t)rw_load_pages;
#pragma omp parallel for
for (uint64_t i = 0; i < num_rw_load_pages * (pagesize/sizeof(*p)); ++i)
p[i] = i;
}
cerr << "Initialization Complete\n";
}
mutex lock;
uint64_t churn( int tnum ) {
uint64_t cnt = 0;
uint64_t idx;
uint64_t* p = (uint64_t*)churn_pages;
mt19937 gen(tnum);
uniform_int_distribution<uint64_t> rnd_int(0, ((num_churn_pages*(pagesize/sizeof(*p)))-1));
while ( !time_to_stop ) {
idx = rnd_int(gen);
if (p[idx] != idx) {
lock.lock();
cerr << hex << "churn() " << p[idx] << " != " << idx << " at address " << &p[idx] << endl;
lock.unlock();
break;
}
}
return cnt;
}
void load_read(int tnum) {
uint64_t* p = (uint64_t*)read_load_pages;
tnum = tnum + 2048;
mt19937 gen(tnum);
uniform_int_distribution<uint64_t> rnd_int(0, ((num_read_load_pages*(pagesize/sizeof(*p)))-1));
while ( !time_to_stop ) {
uint64_t idx = rnd_int(gen);
if (p[idx] != idx) {
lock.lock();
cerr << "load_read *(uint64_t*)" << &p[idx] << "=" << p[idx] << " != " << idx << endl;
lock.unlock();
break;
}
}
}
// Have a reader going nuts on the write page for fun. No data validation since the writer is changing it from underneath us.
void load_rw_read(int tnum) {
uint64_t* p = (uint64_t*)rw_load_pages;
tnum = tnum + tnum * 53;
mt19937 gen(tnum);
uniform_int_distribution<uint64_t> rnd_int(0, ((num_rw_load_pages*(pagesize/sizeof(*p)))-1));
while ( !time_to_stop ) {
uint64_t idx = rnd_int(gen);
g_count += p[idx];
}
}
void load_rw_write() {
uint64_t cnt = 0;
uint64_t* p = (uint64_t*)((uint64_t)rw_load_pages);
const int num_entries = num_rw_load_pages * pagesize/sizeof(*p);
omp_set_num_threads(options.num_load_writer_threads);
while ( !time_to_stop ) {
uint64_t cnt_base = cnt;
#pragma omp parallel for
for (int i = 0; i < num_entries; ++i) {
p[i] = cnt_base + i;
}
#pragma omp parallel for
for (int i = 0; i < num_entries; ++i) {
if (p[i] != (cnt_base + i)) {
#pragma omp critical
{
lock.lock();
cerr << "load_rw_write *(uint64_t*)" << &p[i] << "=" << p[i] << " != " << (cnt_base+i) << ": (" << cnt_base << "+" << i << "=" << (cnt_base+i) << ") - " << p[i] << " = " << ((cnt_base+i)-p[i]) << endl;
if (i != 0)
cerr << "load_rw_write *(uint64_t*)" << &p[0] << "=" << p[0] << " , " << (cnt_base+0) << ": (" << cnt_base << "+" << 0 << "=" << (cnt_base+0) << ") - " << p[0] << " = " << ((cnt_base+0)-p[0]) << endl;
lock.unlock();
}
exit(1);
}
}
cnt += pagesize/sizeof(*p);
}
}
};
int main(int argc, char **argv)
{
pageiotest test{argc, argv};
test.start();
test.run();
test.stop();
return 0;
}
Includes¶
../utility/commandline.hpp
../utility/umap_file.hpp
algorithm
cassert
chrono
cstdint
iostream
mutex
omp.h
options.h
(File options.h)random
(File run_random_vector.cpp)thread
umap/umap.h
utmpx.h
vector
(File run_random_vector.cpp)
Namespaces¶
Classes¶
Functions¶
Variables¶
File commandline.hpp¶
↰ Parent directory (utility
)
Contents
Definition (utility/commandline.hpp
)¶
↰ Return to documentation for file (utility/commandline.hpp
)
/*
* This file is part of UMAP. For copyright information see the COPYRIGHT file
* in the top level directory, or at
* https://github.com/LLNL/umap/blob/master/COPYRIGHT. This program is free
* software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License (as published by the Free Software
* Foundation) version 2.1 dated February 1999. This program is distributed in
* the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the terms and conditions of the GNU Lesser General Public License for more
* details. You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _COMMANDLING_HPP
#define _COMMANDLING_HPP
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#include <stdint.h>
#include <iostream> // cout/cerr
#include <unistd.h> // getopt()
#include <getopt.h> // duh...
#include "umap/umap.h"
namespace utility {
typedef struct {
int initonly; // Just perform initialization, then quit
int noinit; // Init already done, so skip it
int usemmap;
int shuffle;
long pagesize;
uint64_t numpages;
uint64_t numthreads;
uint64_t bufsize;
uint64_t uffdthreads;
uint64_t pages_to_access; // 0 (default) - access all pages
char const* filename; // file name or basename
char const* dirname; // dir name or basename
} umt_optstruct_t;
static char const* DIRNAME = "/mnt/intel/";
static char const* FILENAME = "abc";
const uint64_t NUMPAGES = 10000000;
const uint64_t NUMTHREADS = 2;
const uint64_t BUFFERSIZE = 16;
using namespace std;
static void usage(char* pname)
{
cerr
<< "Usage: " << pname << " [--initonly] [--noinit] [--directio]"
<< " [--usemmap] [-p #] [-t #] [-b #] [-f name]\n\n"
<< " --help - This message\n"
<< " --initonly - Initialize file, then stop\n"
<< " --noinit - Use previously initialized file\n"
<< " --usemmap - Use mmap instead of umap\n"
<< " --shuffle - Shuffle memory accesses (instead of sequential access)\n"
<< " -p # of pages - default: " << NUMPAGES << endl
<< " -t # of threads - default: " << NUMTHREADS << endl
<< " -u # of uffd threads - default: " << umap_cfg_get_uffdthreads() << " worker threads\n"
<< " -b # page buffer size - default: " << umap_cfg_get_bufsize() << " Pages\n"
<< " -a # pages to access - default: 0 - access all pages\n"
<< " -f [file name] - backing file name. Or file basename if multiple files\n"
<< " -d [directory name] - backing directory name. Or dir basename if multiple dirs\n"
<< " -P # page size - default: " << umap_cfg_get_pagesize() << endl;
exit(1);
}
void umt_getoptions(utility::umt_optstruct_t* testops, int argc, char *argv[])
{
int c;
char *pname = argv[0];
testops->initonly = 0;
testops->noinit = 0;
testops->usemmap = 0;
testops->shuffle = 0;
testops->pages_to_access = 0;
testops->numpages = NUMPAGES;
testops->numthreads = NUMTHREADS;
testops->bufsize = umap_cfg_get_bufsize();
testops->uffdthreads = umap_cfg_get_uffdthreads();
testops->filename = FILENAME;
testops->dirname = DIRNAME;
testops->pagesize = umap_cfg_get_pagesize();
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"initonly", no_argument, &testops->initonly, 1 },
{"noinit", no_argument, &testops->noinit, 1 },
{"usemmap", no_argument, &testops->usemmap, 1 },
{"shuffle", no_argument, &testops->shuffle, 1 },
{"help", no_argument, NULL, 0 },
{0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "p:t:f:b:d:u:a:P:", long_options, &option_index);
if (c == -1)
break;
switch(c) {
case 0:
if (long_options[option_index].flag != 0)
break;
usage(pname);
break;
case 'P':
if ((testops->pagesize = strtol(optarg, nullptr, 0)) > 0) {
if (umap_cfg_set_pagesize(testops->pagesize) < 0) {
goto R0;
}
break;
}
goto R0;
case 'p':
if ((testops->numpages = strtoull(optarg, nullptr, 0)) > 0)
break;
goto R0;
case 't':
if ((testops->numthreads = strtoull(optarg, nullptr, 0)) > 0)
break;
else goto R0;
case 'b':
if ((testops->bufsize = strtoull(optarg, nullptr, 0)) > 0)
break;
else goto R0;
case 'u':
if ((testops->uffdthreads = strtoull(optarg, nullptr, 0)) > 0)
break;
else goto R0;
case 'a':
if ((testops->pages_to_access = strtoull(optarg, nullptr, 0)) >= 0)
break;
else goto R0;
case 'd':
testops->dirname = optarg;
break;
case 'f':
testops->filename = optarg;
break;
default:
R0:
usage(pname);
}
}
if (testops->numpages < testops->pages_to_access) {
cerr << "Invalid -a argument " << testops->pages_to_access << "\n";
usage(pname);
}
if (optind < argc) {
cerr << "Unknown Arguments: ";
while (optind < argc)
cerr << "\"" << argv[optind++] << "\" ";
cerr << endl;
usage(pname);
}
/*
* Note: Care must be taken when configuring the number of threads
* and the buffer size of umap. When the buffer size is set, it
* apportions the buffer evenly to the umap threads. So setting the
* buffer size requires that the number of threads be set properly
* first.
*/
if (testops->uffdthreads != umap_cfg_get_uffdthreads())
umap_cfg_set_uffdthreads(testops->uffdthreads);
umap_cfg_set_bufsize(testops->bufsize);
}
long umt_getpagesize(void)
{
return umap_cfg_get_pagesize();
}
}
#endif // _COMMANDLING_HPP
Includes¶
getopt.h
iostream
stdint.h
umap/umap.h
unistd.h
Included By¶
Namespaces¶
Classes¶
Functions¶
Defines¶
File compute_degree_distribution.cpp¶
↰ Parent directory (bfs
)
Definition (bfs/compute_degree_distribution.cpp
)¶
↰ Return to documentation for file (bfs/compute_degree_distribution.cpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <algorithm>
/// This is a utility program to compute a degree distribution
/// This program treat the input files as directed graph
/// Usage:
/// ./compute_degree_distribution [out file name] [edge list file names]
int main(int argc, char **argv) {
if (argc < 3) {
std::cerr << "Wrong number of arguments" << std::endl;
std::abort();
}
std::string out_file_name(argv[1]);
// -- Count degree -- //
std::unordered_map<uint64_t, uint64_t> degree_table;
for (int i = 2; i < argc; ++i) {
std::ifstream input_edge_list(argv[i]);
if (!input_edge_list.is_open()) {
std::cerr << "Cannot open " << argv[i] << std::endl;
continue;
}
uint64_t source;
uint64_t destination;
while (input_edge_list >> source >> destination) {
if (degree_table.count(source) == 0) {
degree_table[source] = 0;
}
++degree_table[source];
}
}
// -- Compute degree distribution table -- //
std::unordered_map<uint64_t, uint64_t> degree_dist_table;
for (const auto &item : degree_table) {
const uint64_t degree = item.second;
if (degree_dist_table.count(degree) == 0) {
degree_dist_table[degree] = 0;
}
++degree_dist_table[degree];
}
// -- Sort the degree distribution table -- //
std::vector<std::pair<uint64_t, uint64_t>> sorted_degree_dist_table;
for (const auto &item : degree_dist_table) {
const uint64_t degree = item.first;
const uint64_t count = item.second;
sorted_degree_dist_table.emplace_back(degree, count);
}
std::sort(sorted_degree_dist_table.begin(), sorted_degree_dist_table.end(),
[](const std::pair<uint64_t, uint64_t> &lh, const std::pair<uint64_t, uint64_t> &rh) {
return (lh.first < rh.first); // Sort in the ascending order of degree
});
// -- Dump the sorted degree distribution table -- //
std::ofstream ofs(out_file_name);
if (!ofs.is_open()) {
std::cerr << "Cannot open " << out_file_name << std::endl;
std::abort();
}
ofs << "Degree\tCount" << std::endl;
for (const auto &item : sorted_degree_dist_table) {
const uint64_t degree = item.first;
const uint64_t count = item.second;
ofs << degree << " " << count << "\n";
}
ofs.close();
std::cout << "Finished degree distribution computation" << std::endl;
return 0;
}
Includes¶
algorithm
fstream
iostream
string
unordered_map
vector
(File run_random_vector.cpp)
Functions¶
File file.hpp¶
↰ Parent directory (utility
)
Definition (utility/file.hpp
)¶
↰ Return to documentation for file (utility/file.hpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LIB_UTILITY_FILE_HPP
#define LIB_UTILITY_FILE_HPP
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <string>
namespace utility {
void extend_file_size_manually(const int fd, const ssize_t file_size) {
auto buffer = new unsigned char[4096];
for (off_t i = 0; i < file_size / 4096; ++i) {
::pwrite(fd, buffer, 4096, i * 4096);
}
const size_t remained_size = file_size % 4096;
if (remained_size > 0)
::pwrite(fd, buffer, remained_size, file_size - remained_size);
::sync();
delete[] buffer;
}
bool extend_file_size(const int fd, const size_t file_size) {
/// ----- extend the file if its size is smaller than that of mapped area ----- ///
#ifdef __linux__
struct stat statbuf;
if (::fstat(fd, &statbuf) == -1) {
::perror("fstat");
std::cerr << "errno: " << errno << std::endl;
return false;
}
if (::llabs(statbuf.st_size) < static_cast<ssize_t>(file_size)) {
if (::ftruncate(fd, file_size) == -1) {
::perror("ftruncate");
std::cerr << "errno: " << errno << std::endl;
return false;
}
}
#else
#warning "Manually extend file size"
extend_file_size_manually(fd, file_size);
#endif
return true;
}
bool extend_file_size(const std::string &file_name, const size_t file_size) {
const int fd = ::open(file_name.c_str(), O_RDWR);
if (fd == -1) {
::perror("open");
std::cerr << "errno: " << errno << std::endl;
return false;
}
if (!extend_file_size(fd, file_size)) return false;
::close(fd);
return true;
}
bool create_file(const std::string &file_name) {
const int fd = ::open(file_name.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
::perror("open");
std::cerr << "errno: " << errno << std::endl;
return false;
}
::close(fd);
return true;
}
} // namespace utility
#endif //LIB_UTILITY_FILE_HPP
Includes¶
fcntl.h
iostream
string
sys/resource.h
sys/stat.h
sys/time.h
unistd.h
Included By¶
Namespaces¶
File generate_edge_list.cpp¶
↰ Parent directory (bfs/rmat_edge_generator
)
Definition (bfs/rmat_edge_generator/generate_edge_list.cpp
)¶
↰ Return to documentation for file (bfs/rmat_edge_generator/generate_edge_list.cpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "rmat_edge_generator.hpp"
// ---------------------------------------- //
// Option
// ---------------------------------------- //
struct rmat_option_t {
uint64_t seed{123};
uint64_t vertex_scale{17};
uint64_t edge_count{(1ULL << 17) * 16};
double a{0.57};
double b{0.19};
double c{0.19};
bool scramble_id{true};
bool generate_both_directions{true};
};
bool parse_options(int argc, char **argv, rmat_option_t *option, std::string *out_edge_list_file_name) {
int p;
while ((p = getopt(argc, argv, "o:s:v:e:a:b:c:r:u:")) != -1) {
switch (p) {
case 'o':*out_edge_list_file_name = optarg; // required
break;
case 's':option->seed = std::stoull(optarg);
break;
case 'v':option->vertex_scale = std::stoull(optarg);
break;
case 'e':option->edge_count = std::stoull(optarg);
break;
case 'a':option->a = std::stod(optarg);
break;
case 'b':option->b = std::stod(optarg);
break;
case 'c':option->c = std::stod(optarg);
break;
case 'r':option->scramble_id = static_cast<bool>(std::stoi(optarg));
break;
case 'u':option->generate_both_directions = static_cast<bool>(std::stoi(optarg));
break;
default:std::cerr << "Illegal option" << std::endl;
std::abort();
}
}
if (out_edge_list_file_name->empty()) {
std::cerr << "edge list file name (-o option) is required" << std::endl;
std::abort();
}
std::cout << "seed: " << option->seed
<< "\nvertex_scale: " << option->vertex_scale
<< "\nedge_count: " << option->edge_count
<< "\na: " << option->a
<< "\nb: " << option->b
<< "\nc: " << option->c
<< "\nscramble_id: " << static_cast<int>(option->scramble_id)
<< "\ngenerate_both_directions: " << static_cast<int>(option->generate_both_directions)
<< "\nout_edge_list_file_name: " << *out_edge_list_file_name << std::endl;
return true;
}
// ---------------------------------------- //
// Main
// ---------------------------------------- //
int main(int argc, char **argv) {
rmat_option_t rmat_option;
std::string out_edge_list_file_name;
parse_options(argc, argv, &rmat_option, &out_edge_list_file_name);
rmat_edge_generator rmat(rmat_option.seed, rmat_option.vertex_scale, rmat_option.edge_count,
rmat_option.a, rmat_option.b, rmat_option.c,
1.0 - (rmat_option.a + rmat_option.b + rmat_option.c),
rmat_option.scramble_id, rmat_option.generate_both_directions);
std::ofstream edge_list_file(out_edge_list_file_name);
if (!edge_list_file.is_open()) {
std::cerr << "Cannot open " << out_edge_list_file_name << std::endl;
std::abort();
}
for (auto edge : rmat) {
edge_list_file << edge.first << " " << edge.second << "\n";
}
edge_list_file.close();
std::cout << "Finished edge list generation" << std::endl;
return 0;
}
Includes¶
fstream
iostream
rmat_edge_generator.hpp
(File rmat_edge_generator.hpp)string
unistd.h
vector
(File run_random_vector.cpp)
Classes¶
File hash.hpp¶
↰ Parent directory (bfs/rmat_edge_generator
)
Definition (bfs/rmat_edge_generator/hash.hpp
)¶
↰ Return to documentation for file (bfs/rmat_edge_generator/hash.hpp
)
/*
* This code is coming from the following project
* /
/ *
* Copyright (c) 2013, Lawrence Livermore National Security, LLC.
* Produced at the Lawrence Livermore National Laboratory.
* Written by Roger Pearce <rpearce@llnl.gov>.
* LLNL-CODE-644630.
* All rights reserved.
*
* This file is part of HavoqGT, Version 0.1.
* For details, see https://computation.llnl.gov/casc/dcca-pub/dcca/Downloads.html
*
* Please also read this link – Our Notice and GNU Lesser General Public License.
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (as published by the Free
* Software Foundation) version 2.1 dated February 1999.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the terms and conditions of the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
*
* Our Preamble Notice
*
* A. This notice is required to be provided under our contract with the
* U.S. Department of Energy (DOE). This work was produced at the Lawrence
* Livermore National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE.
*
* B. Neither the United States Government nor Lawrence Livermore National
* Security, LLC nor any of their employees, makes any warranty, express or
* implied, or assumes any liability or responsibility for the accuracy,
* completeness, or usefulness of any information, apparatus, product, or process
* disclosed, or represents that its use would not infringe privately-owned rights.
*
* C. Also, reference herein to any specific commercial products, process, or
* services by trade name, trademark, manufacturer or otherwise does not
* necessarily constitute or imply its endorsement, recommendation, or favoring by
* the United States Government or Lawrence Livermore National Security, LLC. The
* views and opinions of authors expressed herein do not necessarily state or
* reflect those of the United States Government or Lawrence Livermore National
* Security, LLC, and shall not be used for advertising or product endorsement
* purposes.
*
*/
#ifndef BFS_HASH_HPP
#define BFS_HASH_HPP
#include <cstdint>
namespace rmat_edge_generator_detail {
///
/// Hash functions
///
/// \todo requires documentation!
/// \todo requires testing!
inline uint32_t hash32(uint32_t a) {
a = (a + 0x7ed55d16) + (a << 12);
a = (a ^ 0xc761c23c) ^ (a >> 19);
a = (a + 0x165667b1) + (a << 5);
a = (a + 0xd3a2646c) ^ (a << 9);
a = (a + 0xfd7046c5) + (a << 3);
a = (a ^ 0xb55a4f09) ^ (a >> 16);
return a;
}
inline uint16_t hash16(uint16_t a) {
a = (a + 0x5d16) + (a << 6);
a = (a ^ 0xc23c) ^ (a >> 9);
a = (a + 0x67b1) + (a << 5);
a = (a + 0x646c) ^ (a << 7);
a = (a + 0x46c5) + (a << 3);
a = (a ^ 0x4f09) ^ (a >> 8);
return a;
}
inline uint64_t shifted_n_hash32(uint64_t input, int n) {
uint64_t to_hash = input >> n;
uint64_t mask = 0xFFFFFFFF;
to_hash &= mask;
to_hash = hash32(to_hash);
to_hash <<= n;
mask <<= n;
//clear bits
input &= ~mask;
input |= to_hash;
return input;
}
inline uint64_t shifted_n_hash16(uint64_t input, int n) {
uint64_t to_hash = input >> n;
uint64_t mask = 0xFFFF;
to_hash &= mask;
to_hash = hash16(to_hash);
to_hash <<= n;
mask <<= n;
//clear bits
input &= ~mask;
input |= to_hash;
return input;
}
inline uint64_t hash_nbits(uint64_t input, int n) {
//std::cout << "hash_nbits(" << input << ", " << n << ") = ";
if (n == 32) {
input = hash32(input);
} else if (n > 32) {
assert(n > 32);
n -= 32;
for (int i = 0; i <= n; ++i) {
input = shifted_n_hash32(input, i);
}
for (int i = n; i >= 0; --i) {
input = shifted_n_hash32(input, i);
}
} else if (n < 32) {
assert(n < 32);
assert(n > 16 && "Hashing less than 16bits is not supported");
n -= 16;
for (int i = 0; i <= n; ++i) {
input = shifted_n_hash16(input, i);
}
for (int i = n; i >= 0; --i) {
input = shifted_n_hash16(input, i);
}
}
//std::cout << input << std::endl;
return input;
}
} // namespace rmat_edge_generator_detail
#endif //BFS_HASH_HPP
Includes¶
cstdint
Included By¶
Namespaces¶
File ingest_edge_list.cpp¶
↰ Parent directory (bfs
)
Definition (bfs/ingest_edge_list.cpp
)¶
↰ Return to documentation for file (bfs/ingest_edge_list.cpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <tuple>
#include <cstring>
#include "../utility/bitmap.hpp"
#include "../utility/mmap.hpp"
#include "../utility/file.hpp"
std::pair<uint64_t, uint64_t>
check_edge_list(const std::vector<std::string> &edge_list_file_names) {
uint64_t max_id = 0;
size_t num_edges = 0;
std::cout << "---------- Find max vertex ID and count #of edges ----------" << std::endl;
#ifdef _OPENMP
#pragma omp parallel for reduction(+:num_edges), reduction(max : max_id)
#endif
for (size_t i = 0; i < edge_list_file_names.size(); ++i) {
std::ifstream ifs(edge_list_file_names[i]);
if (!ifs.is_open()) {
std::cerr << "Can not open " << edge_list_file_names[i] << std::endl;
std::abort();
}
std::cout << "Reading " << edge_list_file_names[i] << std::endl;
uint64_t src, trg;
while (ifs >> src >> trg) {
max_id = std::max(src, max_id);
max_id = std::max(trg, max_id);
++num_edges;
}
}
return std::make_pair(max_id, num_edges);
}
void ingest_edges(void *const map_raw_address, const uint64_t max_id, const std::vector<std::string> &edge_list_file_names) {
uint64_t *const index = new uint64_t[max_id + 2];
for (size_t i = 0; i < max_id + 2; ++i) index[i] = 0;
std::cout << static_cast<double>((max_id + 2) * sizeof(uint64_t) / (1ULL << 30))
<< " GB is allocated for index" << std::endl;
std::cout << "---------- Count degree ----------" << std::endl;
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (size_t i = 0; i < edge_list_file_names.size(); ++i) {
std::cout << "Reading " << edge_list_file_names[i] << std::endl;
std::ifstream edge_stream(edge_list_file_names[i]);
if (!edge_stream.is_open()) {
std::cerr << "Can not open " << edge_list_file_names[i] << std::endl;
std::abort();
}
uint64_t source, target;
while (edge_stream >> source >> target) {
#ifdef _OPENMP
#pragma omp atomic
#endif
++index[source];
}
}
std::cout << "---------- Construct index ----------" << std::endl;
for (size_t i = max_id + 1; i > 0; --i) {
index[i] = index[i - 1];
}
index[0] = 0;
for (size_t i = 0; i < max_id + 1; ++i) {
index[i + 1] += index[i];
}
std::cout << "---------- Writing index ----------" << std::endl;
uint64_t *index_map = static_cast<uint64_t *>(map_raw_address);
std::memcpy(index_map, index, (max_id + 2) * sizeof(uint64_t));
std::cout << "---------- Load edges ----------" << std::endl;
const std::ptrdiff_t edges_offset = static_cast<std::ptrdiff_t>(max_id) + 2;
uint64_t *edges_map = static_cast<uint64_t *>(map_raw_address) + edges_offset;
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (size_t i = 0; i < edge_list_file_names.size(); ++i) {
std::cout << "Reading " << edge_list_file_names[i] << std::endl;
std::ifstream edge_stream(edge_list_file_names[i]);
uint64_t source, target;
while (edge_stream >> source >> target) {
size_t pos;
#ifdef _OPENMP
#pragma omp atomic capture
#endif
pos = index[source]++;
edges_map[pos] = target;
}
}
delete[] index;
}
void parse_options(int argc, char **argv,
std::string &graph_file_name,
std::vector<std::string> &edge_list_file_names) {
graph_file_name = "";
char c;
while ((c = getopt(argc, argv, "g:h")) != -1) {
switch (c) {
case 'g': /// Required
graph_file_name = optarg;
break;
case 'h':
// usage();
break;
}
}
for (int index = optind; index < argc; index++) {
edge_list_file_names.push_back(argv[index]);
}
}
int main(int argc, char **argv) {
std::string graph_file_name;
std::vector<std::string> edge_list_file_names;
parse_options(argc, argv, graph_file_name, edge_list_file_names);
uint64_t max_id;
size_t num_edges;
std::tie(max_id, num_edges) = check_edge_list(edge_list_file_names);
std::cout << "num_vertices: " << max_id + 1 << std::endl;
std::cout << "num_edges: " << num_edges << std::endl;
/// ----- create and map output (graph) file ----- ///
const size_t graph_size = (max_id + 2 + num_edges) * sizeof(uint64_t);
if (!utility::create_file(graph_file_name)) {
std::cerr << "Failed to create a file: " << graph_file_name << std::endl;
std::abort();
}
if (!utility::extend_file_size(graph_file_name, graph_size)) {
std::cerr << "Failed to extend a file: " << graph_file_name << std::endl;
std::abort();
}
int fd = -1;
void *map_raw_address = nullptr;
std::tie(fd, map_raw_address) = utility::map_file_write_mode(graph_file_name, nullptr, graph_size, 0);
if (fd == -1 || map_raw_address == nullptr) {
std::cerr << "Failed to map a file with write mode: " << graph_file_name << std::endl;
std::abort();
}
/// ----- ingest edges ----- ///
ingest_edges(map_raw_address, max_id, edge_list_file_names);
/// ----- closing ----- ///
utility::munmap(map_raw_address, graph_size, true);
std::cout << "Edge list ingestion is finished" << std::endl;
return 0;
}
Includes¶
../utility/bitmap.hpp
../utility/file.hpp
../utility/mmap.hpp
algorithm
cstring
fcntl.h
fstream
iostream
string
sys/mman.h
tuple
unistd.h
vector
(File run_random_vector.cpp)
File INSTRUCTION.md¶
↰ Parent directory (median_calculation
)
Definition (median_calculation/INSTRUCTION.md
)¶
↰ Return to documentation for file (median_calculation/INSTRUCTION.md
)
# Build
Under construction...
# Run
```sh
$ ls /mnt/ssd/
asteroid_sim_epoch10.fits asteroid_sim_epoch2.fits asteroid_sim_epoch4.fits asteroid_sim_epoch6.fits asteroid_sim_epoch8.fits
asteroid_sim_epoch1.fits asteroid_sim_epoch3.fits asteroid_sim_epoch5.fits asteroid_sim_epoch7.fits asteroid_sim_epoch9.fits
$ cd /path/to/umap/build/directory/
$ env NUM_VECTORS=10000 ./tests/median_calculation/run_random_vector -f /mnt/ssd/asteroid_sim_epoch
```
File mmap.hpp¶
↰ Parent directory (utility
)
Definition (utility/mmap.hpp
)¶
↰ Return to documentation for file (utility/mmap.hpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SIMPLE_BFS_MMAP_UTILITY_HPP
#define SIMPLE_BFS_MMAP_UTILITY_HPP
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <cstddef>
#include "file.hpp"
namespace utility {
/// \brief Get the page size
/// \return The size of page size. Return -1 for error cases.
ssize_t get_page_size() {
const ssize_t page_size = ::sysconf(_SC_PAGE_SIZE);
if (page_size == -1) {
::perror("sysconf(_SC_PAGE_SIZE)");
std::cerr << "errno: " << errno << std::endl;
}
return page_size;
}
/// \brief Maps a file checking errors
/// \param addr Same as mmap(2)
/// \param length Same as mmap(2)
/// \param protection Same as mmap(2)
/// \param flags Same as mmap(2)
/// \param fd Same as mmap(2)
/// \param offset Same as mmap(2)
/// \return On success, returns a pointer to the mapped area.
/// On error, nullptr is returned.
void *map_file(void *const addr, const size_t length, const int protection, const int flags,
const int fd, const off_t offset) {
const ssize_t page_size = get_page_size();
if (page_size == -1) {
return nullptr;
}
if ((std::ptrdiff_t)addr % page_size != 0) {
std::cerr << "address (" << addr << ") is not page aligned ("
<< ::sysconf(_SC_PAGE_SIZE) << ")" << std::endl;
return nullptr;
}
if (offset % page_size != 0) {
std::cerr << "offset (" << offset << ") is not a multiple of the page size (" << ::sysconf(_SC_PAGE_SIZE) << ")"
<< std::endl;
return nullptr;
}
/// ----- Map the file ----- ///
void *mapped_addr = ::mmap(addr, length, protection, flags, fd, offset);
if (mapped_addr == MAP_FAILED) {
::perror("mmap");
std::cerr << "errno: " << errno << std::endl;
return nullptr;
}
if ((std::ptrdiff_t)mapped_addr % page_size != 0) {
std::cerr << "mapped address (" << mapped_addr << ") is not page aligned ("
<< ::sysconf(_SC_PAGE_SIZE) << ")" << std::endl;
return nullptr;
}
return mapped_addr;
}
/// \brief Maps a file with read mode
/// \param file_name The name of file to be mapped
/// \param addr Normally nullptr; if this is not nullptr the kernel takes it as a hint about where to place the mapping
/// \param length The length of the map
/// \param offset The offset in the file
/// \return On Success, returns a pair of the file descriptor of the file and the starting address for the map.
/// On error, retuns a pair of -1 and nullptr.
std::pair<int, void *> map_file_read_mode(const std::string &file_name, void *const addr,
const size_t length, const off_t offset,
const int additional_flags = 0) {
/// ----- Open the file ----- ///
const int fd = ::open(file_name.c_str(), O_RDONLY);
if (fd == -1) {
::perror("open");
std::cerr << "errno: " << errno << std::endl;
return std::make_pair(-1, nullptr);
}
/// ----- Map the file ----- ///
void *mapped_addr = map_file(addr, length, PROT_READ, MAP_SHARED | additional_flags, fd, offset);
if (mapped_addr == nullptr) {
close(fd);
return std::make_pair(-1, nullptr);
}
return std::make_pair(fd, mapped_addr);
}
/// \brief Maps a file with write mode
/// \param file_name The name of a file to be mapped
/// \param addr Normally nullptr; if this is not nullptr the kernel takes it as a hint about where to place the mapping
/// \param length The length of the map
/// \param offset The offset in the file
/// \return On Success, returns a pair of the file descriptor of the file and the starting address for the map.
/// On error, retuns a pair of -1 and nullptr.
std::pair<int, void *> map_file_write_mode(const std::string &file_name, void *const addr,
const size_t length, const off_t offset,
const int additional_flags = 0) {
/// ----- Open the file ----- ///
const int fd = ::open(file_name.c_str(), O_RDWR);
if (fd == -1) {
::perror("open");
std::cerr << "errno: " << errno << std::endl;
return std::make_pair(-1, nullptr);
}
/// ----- Map the file ----- ///
void *mapped_addr = map_file(addr, length, PROT_READ | PROT_WRITE, MAP_SHARED | additional_flags, fd, offset);
if (mapped_addr == nullptr) {
close(fd);
return std::make_pair(-1, nullptr);
}
return std::make_pair(fd, mapped_addr);
}
void msync(void *const addr, const size_t length) {
if (::msync(addr, length, MS_SYNC) != 0) {
::perror("msync");
std::cerr << "errno: " << errno << std::endl;
}
}
void munmap(void *const addr, const size_t length, const bool call_msync) {
if (call_msync) msync(addr, length);
if (::munmap(addr, length) != 0) {
::perror("munmap");
std::cerr << "errno: " << errno << std::endl;
}
}
} // namespace utility
#endif //SIMPLE_BFS_MMAP_UTILITY_HPP
Includes¶
cstddef
fcntl.h
file.hpp
(File file.hpp)iostream
stdio.h
stdlib.h
sys/mman.h
sys/stat.h
sys/types.h
unistd.h
Namespaces¶
File nvmebenchmark.cpp¶
↰ Parent directory (pfbenchmark
)
Definition (pfbenchmark/nvmebenchmark.cpp
)¶
↰ Return to documentation for file (pfbenchmark/nvmebenchmark.cpp
)
/* This file is part of UMAP. For copyright information see the COPYRIGHT
* file in the top level directory, or at https://github.com/LLNL/umap/blob/master/COPYRIGHT
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (as published by the Free
* Software Foundation) version 2.1 dated February 1999. This program is distributed in
* the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED
* WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the terms and conditions of the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*
* This program is a benchmark for NVME device I/O bandwidth which provides the average
* time in nanoseconds for performing the following I/O operations:
*
* 1) Page (4K) writes to a file on the NVME device
* 2) Page (4K) reads from a file on the NVME device
*
* A number of threads may be specified on the command line to enable concurrent I/O
* access within the file. Further, the file may be accessed sequentially (default)
* or randomly (if "--shuffle" command line option is specified).
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#include <iostream>
#include <chrono>
#include <omp.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <string>
#include <sstream>
#include <vector>
#include <random>
#include <algorithm>
#include <iterator>
#include "umap/umap.h"
#include "../utility/commandline.hpp"
using namespace std;
using namespace chrono;
static uint64_t pagesize;
static uint64_t pages_to_access;
static char** tmppagebuf; // One per thread
static int fd;
static utility::umt_optstruct_t options;
vector<uint64_t> shuffled_indexes;
void do_write_pages(uint64_t pages)
{
#pragma omp parallel for
for (uint64_t i = 0; i < pages; ++i) {
uint64_t myidx = shuffled_indexes[i];
uint64_t* ptr = (uint64_t*)tmppagebuf[omp_get_thread_num()];
*ptr = myidx * pagesize/sizeof(uint64_t);
if (pwrite(fd, ptr, pagesize, myidx*pagesize) < 0) {
perror("pwrite");
exit(1);
}
}
}
void do_read_pages(uint64_t pages)
{
#pragma omp parallel for
for (uint64_t i = 0; i < pages; ++i) {
uint64_t myidx = shuffled_indexes[i];
uint64_t* ptr = (uint64_t*)tmppagebuf[omp_get_thread_num()];
if (pread(fd, ptr, pagesize, myidx*pagesize) < 0) {
perror("pread");
exit(1);
}
if ( *ptr != myidx * pagesize/sizeof(uint64_t) ) {
cout << i << " " << myidx << " " << *ptr << " != " << (myidx * pagesize/sizeof(uint64_t)) << "\n";
exit(1);
}
}
}
int read_pages(int argc, char **argv)
{
fd = open(options.filename, O_RDWR | O_LARGEFILE | O_DIRECT);
if (fd == -1) {
perror("open failed\n");
exit(1);
}
auto start_time = chrono::high_resolution_clock::now();
do_read_pages(pages_to_access);
auto end_time = chrono::high_resolution_clock::now();
cout << "nvme,"
<< "+IO,"
<< (( options.shuffle == 1) ? "shuffle" : "seq") << ","
<< "read,"
<< options.numthreads << ","
<< 0 << ","
<< chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count() / pages_to_access << "\n";
close(fd);
return 0;
}
int write_pages(int argc, char **argv)
{
if ( !options.noinit ) {
cout << "Removing " << options.filename << "\n";
unlink(options.filename);
cout << "Creating " << options.filename << "\n";
fd = open(options.filename, O_RDWR | O_LARGEFILE | O_DIRECT | O_CREAT, S_IRUSR | S_IWUSR);
}
else {
fd = open(options.filename, O_RDWR | O_LARGEFILE | O_DIRECT);
}
if (fd == -1) {
perror("open failed\n");
exit(1);
}
auto start_time = chrono::high_resolution_clock::now();
do_write_pages(pages_to_access);
auto end_time = chrono::high_resolution_clock::now();
cout << "nvme,"
<< "+IO,"
<< (( options.shuffle == 1) ? "shuffle" : "seq") << ","
<< "write,"
<< options.numthreads << ","
<< 0 << ","
<< chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count() / pages_to_access << "\n";
close(fd);
return 0;
}
int main(int argc, char **argv)
{
int rval = 0;
std::random_device rd;
std::mt19937 g(rd());
umt_getoptions(&options, argc, argv);
for (uint64_t i = 0; i < options.numpages; ++i)
shuffled_indexes.push_back(i);
pages_to_access = options.pages_to_access ? options.pages_to_access : options.numpages;
if ( options.shuffle )
std::shuffle(shuffled_indexes.begin(), shuffled_indexes.end(), g);
omp_set_num_threads(options.numthreads);
pagesize = (uint64_t)utility::umt_getpagesize();
tmppagebuf = (char**)calloc(options.numthreads, sizeof(char*));
for (int i = 0; i < options.numthreads; ++i) {
if (posix_memalign((void**)&tmppagebuf[i], (uint64_t)512, pagesize)) {
cerr << "ERROR: posix_memalign: failed\n";
exit(1);
}
if (tmppagebuf[i] == nullptr) {
cerr << "Unable to allocate " << pagesize << " bytes for temporary buffer\n";
exit(1);
}
}
if (strcmp(argv[0], "nvmebenchmark-write") == 0)
rval = write_pages(argc, argv);
else if (strcmp(argv[0], "nvmebenchmark-read") == 0)
rval = read_pages(argc, argv);
return rval;
}
Includes¶
../utility/commandline.hpp
algorithm
chrono
fcntl.h
iostream
iterator
omp.h
random
(File run_random_vector.cpp)sstream
stdlib.h
string
string.h
umap/umap.h
unistd.h
vector
(File run_random_vector.cpp)
Functions¶
Defines¶
File options.cpp¶
↰ Parent directory (churn
)
Definition (churn/options.cpp
)¶
↰ Return to documentation for file (churn/options.cpp
)
/* This file is part of UMAP. For copyright information see the COPYRIGHT file in the top level directory, or at https://github.com/LLNL/umap/blob/master/COPYRIGHT This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (as published by the Free Software Foundation) version 2.1 dated February 1999. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and conditions of the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#include <iostream> // cout/cerr
#include <unistd.h> // getopt()
#include <getopt.h> // duh...
#include "options.h"
#include "umap/umap.h"
static char const* FILENAME = "/tmp/abc";
static const uint64_t NUMCHURNPAGES = 99;
static const uint64_t NUMLOADPAGES = 1;
static const uint64_t NUMCHURNTHREADS = 48;
static const uint64_t NUMLOADREADERS = 48;
static const uint64_t NUMLOADWRITERS = 48;
static const uint64_t TESTDURATION = 60;
using namespace std;
static void usage(char* pname)
{
cerr
<< "Usage: " << pname << " [Options...]\n\n"
<< " --help - This message\n"
<< " --initonly - Initialize only\n"
<< " --noinit - No Initialization\n"
<< " --directio - Use O_DIRECT for file IO\n"
<< " --usemmap - Use mmap instead of umap\n"
<< " -b # of pages in page buffer - default: " << umap_cfg_get_bufsize() << " Pages\n"
<< " -c # of churn pages - default: " << NUMCHURNPAGES << " Pages\n"
<< " -l # of load pages - default: " << NUMLOADPAGES << " Pages\n"
<< " -t # of churn threads - default: " << NUMCHURNTHREADS << endl
<< " -r # of load reader threads - default: " << NUMLOADREADERS << endl
<< " -w # of load writer threads - default: " << NUMLOADWRITERS << endl
<< " -f [backing file name] - default: " << FILENAME << endl
<< " -d # seconds to run test - default: " << TESTDURATION << " seconds\n";
exit(1);
}
void getoptions(options_t& testops, int& argc, char **argv)
{
int c;
char *pname = argv[0];
testops.iodirect=0;
testops.usemmap=0;
testops.noinit=0;
testops.initonly=0;
testops.num_churn_pages=NUMCHURNPAGES;
testops.num_churn_threads=NUMCHURNTHREADS;
testops.num_load_pages=NUMLOADPAGES;
testops.num_load_reader_threads=NUMLOADREADERS;
testops.num_load_writer_threads=NUMLOADWRITERS;
testops.fn=FILENAME;
testops.testduration=TESTDURATION;
testops.page_buffer_size = umap_cfg_get_bufsize();
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"directio", no_argument, &testops.iodirect, 1 },
{"usemmap", no_argument, &testops.usemmap, 1 },
{"initonly", no_argument, &testops.initonly, 1 },
{"noinit", no_argument, &testops.noinit, 1 },
{"help", no_argument, NULL, 0 },
{0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "b:c:l:t:r:w:f:d:", long_options, &option_index);
if (c == -1)
break;
switch(c) {
case 0:
if (long_options[option_index].flag != 0)
break;
usage(pname);
break;
case 'b':
if ((testops.page_buffer_size = strtoull(optarg, nullptr, 0)) > 0)
break;
goto R0;
case 'c':
if ((testops.num_churn_pages = strtoull(optarg, nullptr, 0)) > 0)
break;
goto R0;
case 'l':
if ((testops.num_load_pages = strtoull(optarg, nullptr, 0)) > 0)
break;
goto R0;
case 'd':
if ((testops.testduration = strtoull(optarg, nullptr, 0)) > 0)
break;
goto R0;
case 'f':
testops.fn = optarg;
break;
case 'w':
if ((testops.num_load_writer_threads = strtoull(optarg, nullptr, 0)) >= 0)
break;
goto R0;
case 'r':
if ((testops.num_load_reader_threads = strtoull(optarg, nullptr, 0)) >= 0)
break;
goto R0;
case 't':
if ((testops.num_churn_threads = strtoull(optarg, nullptr, 0)) >= 0)
break;
goto R0;
default:
R0:
usage(pname);
}
}
if (optind < argc) {
cerr << "Unknown Arguments: ";
while (optind < argc)
cerr << "\"" << argv[optind++] << "\" ";
cerr << endl;
usage(pname);
}
umap_cfg_set_bufsize(testops.page_buffer_size);
}
Includes¶
getopt.h
iostream
options.h
(File options.h)umap/umap.h
unistd.h
Defines¶
File options.h¶
↰ Parent directory (churn
)
Definition (churn/options.h
)¶
↰ Return to documentation for file (churn/options.h
)
/* This file is part of UMAP. For copyright information see the COPYRIGHT file in the top level directory, or at https://github.com/LLNL/umap/blob/master/COPYRIGHT This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (as published by the Free Software Foundation) version 2.1 dated February 1999. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and conditions of the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _OPTIONS_H
#define _OPTIONS_H
#include <stdint.h>
#include "options.h"
typedef struct {
int iodirect;
int usemmap;
int initonly;
int noinit;
uint64_t page_buffer_size; // # of pages that page buffer can hold
uint64_t num_churn_pages;
uint64_t num_load_pages;
uint64_t num_churn_threads;
uint64_t num_load_reader_threads;
uint64_t num_load_writer_threads;
char const* fn; // Backing file name
uint64_t testduration; // Duration (in seconds) to run test
} options_t;
void getoptions(options_t&, int&, char **argv);
#endif // _OPTIONS_H
Includes¶
options.h
(File options.h)stdint.h
Included By¶
Classes¶
File pfbenchmark.cpp¶
↰ Parent directory (pfbenchmark
)
Definition (pfbenchmark/pfbenchmark.cpp
)¶
↰ Return to documentation for file (pfbenchmark/pfbenchmark.cpp
)
/* This file is part of UMAP. For copyright information see the COPYRIGHT
* file in the top level directory, or at https://github.com/LLNL/umap/blob/master/COPYRIGHT
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (as published by the Free
* Software Foundation) version 2.1 dated February 1999. This program is distributed in
* the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED
* WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the terms and conditions of the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*
* This program is a benchmark for UMAP page fault handling. The specied backing file
* for UMAP is accessed a page at a time indirectly by accessing pages that have been
* mapped to the file. Read accesses to memory will determine the average nanosecond
* cost for servicing a READ PAGE FAULT and write accesses to memory will determine
* the average cost of WRITE PAGE FAULTs.
*
* A number of threads may be specified on the command line to enable concurrent I/O
* access within the file. Further, the file may be accessed sequentially (default)
* or randomly (if "--shuffle" command line option is specified).
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#include <iostream>
#include <chrono>
#include <omp.h>
#include <string.h>
#include <vector>
#include <random>
#include <algorithm>
#include <iterator>
#include "umap/umap.h"
#include "../utility/umap_file.hpp"
#include "../utility/commandline.hpp"
using namespace std;
using namespace chrono;
static bool usemmap = false;
static uint64_t pagesize;
static uint64_t page_step;
static uint64_t* glb_array;
static utility::umt_optstruct_t options;
static uint64_t pages_to_access;
vector<uint64_t> shuffled_indexes;
void do_write_pages(uint64_t page_step, uint64_t pages)
{
#pragma omp parallel for
for (uint64_t i = 0; i < pages; ++i) {
uint64_t myidx = shuffled_indexes[i];
glb_array[myidx * page_step] = (myidx * page_step);
}
}
uint64_t do_read_pages(uint64_t page_step, uint64_t pages)
{
uint64_t x;
// Weird logic to make sure that compiler doesn't optimize out our read of glb_array[i]
#pragma omp parallel for
for (uint64_t i = 0; i < pages; ++i) {
uint64_t myidx = shuffled_indexes[i];
x = glb_array[myidx * page_step];
if (x != (myidx * page_step)) {
cout << __FUNCTION__ << "glb_array[" << myidx * page_step << "]: (" << glb_array[myidx*page_step] << ") != " << myidx * page_step << "\n";
exit(1);
}
}
return x;
}
uint64_t do_read_modify_write_pages(uint64_t page_step, uint64_t pages)
{
uint64_t x;
// Weird logic to make sure that compiler doesn't optimize out our read of glb_array[i]
#pragma omp parallel for
for (uint64_t i = 0; i < pages; ++i) {
uint64_t myidx = shuffled_indexes[i];
x = glb_array[myidx * page_step];
if (x != (myidx * page_step)) {
cout << __FUNCTION__ << "glb_array[" << myidx * page_step << "]: (" << x << ") != " << myidx * page_step << "\n";
exit(1);
}
else {
glb_array[myidx * page_step] = (myidx * page_step);
x++;
}
}
return x;
}
void print_stats( void )
{
if (!usemmap) {
struct umap_cfg_stats s;
umap_cfg_get_stats(glb_array, &s);
//cout << s.dirty_evicts << " Dirty Evictions\n";
//cout << s.clean_evicts << " Clean Evictions\n";
//cout << s.evict_victims << " Victims\n";
//cout << s.wp_messages << " WP Faults\n";
//cout << s.read_faults << " Read Faults\n";
//cout << s.write_faults << " Write Faults\n";
if (s.sigbus)
cout << s.sigbus << " SIGBUS Signals\n";
if (s.stuck_wp)
cout << s.stuck_wp << " Stuck WP Workarounds\n";
//cout << s.dropped_dups << " Dropped Duplicates\n";
}
}
int read_test(int argc, char **argv)
{
auto start_time = chrono::high_resolution_clock::now();
do_read_pages(page_step, pages_to_access);
auto end_time = chrono::high_resolution_clock::now();
cout << ((options.usemmap == 1) ? "mmap" : "umap") << ","
<< (( options.shuffle == 1) ? "shuffle" : "seq") << ","
<< "read,"
<< options.numthreads << ","
<< options.uffdthreads << ","
<< chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count() / pages_to_access << "\n";
return 0;
}
int write_test(int argc, char **argv)
{
auto start_time = chrono::high_resolution_clock::now();
do_write_pages(page_step, pages_to_access);
auto end_time = chrono::high_resolution_clock::now();
cout << ((options.usemmap == 1) ? "mmap" : "umap") << ","
<< (( options.shuffle == 1) ? "shuffle" : "seq") << ","
<< "write,"
<< options.numthreads << ","
<< options.uffdthreads << ","
<< chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count() / pages_to_access << "\n";
return 0;
}
int read_modify_write_test(int argc, char **argv)
{
auto start_time = chrono::high_resolution_clock::now();
auto end_time = chrono::high_resolution_clock::now();
start_time = chrono::high_resolution_clock::now();
do_read_modify_write_pages(page_step, pages_to_access);
end_time = chrono::high_resolution_clock::now();
cout << ((options.usemmap == 1) ? "mmap" : "umap") << ","
<< (( options.shuffle == 1) ? "shuffle" : "seq") << ","
<< "rmw,"
<< options.numthreads << ","
<< options.uffdthreads << ","
<< chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count() / pages_to_access << "\n";
return 0;
}
int main(int argc, char **argv)
{
int rval = -1;
std::random_device rd;
std::mt19937 g(rd());
umt_getoptions(&options, argc, argv);
for (uint64_t i = 0; i < options.numpages; ++i)
shuffled_indexes.push_back(i);
pages_to_access = options.pages_to_access ? options.pages_to_access : options.numpages;
if ( options.shuffle )
std::shuffle(shuffled_indexes.begin(), shuffled_indexes.end(), g);
options.initonly = 0;
usemmap = (options.usemmap == 1);
omp_set_num_threads(options.numthreads);
pagesize = (uint64_t)utility::umt_getpagesize();
page_step = pagesize/sizeof(uint64_t);
glb_array = (uint64_t*) utility::map_in_file(options.filename, options.initonly,
options.noinit, options.usemmap, pagesize * options.numpages);
if (strcmp(argv[0], "pfbenchmark-read") == 0)
rval = read_test(argc, argv);
else if (strcmp(argv[0], "pfbenchmark-write") == 0)
rval = write_test(argc, argv);
else if (strcmp(argv[0], "pfbenchmark-readmodifywrite") == 0)
rval = read_modify_write_test(argc, argv);
else
cerr << "Unknown test mode " << argv[0] << "\n";
print_stats();
utility::unmap_file(options.usemmap, pagesize * options.numpages, glb_array);
return rval;
}
Includes¶
../utility/commandline.hpp
../utility/umap_file.hpp
algorithm
chrono
iostream
iterator
omp.h
random
(File run_random_vector.cpp)string.h
umap/umap.h
vector
(File run_random_vector.cpp)
Functions¶
Defines¶
File README.md¶
↰ Parent directory (bfs
)
Contents
Definition (bfs/README.md
)¶
↰ Return to documentation for file (bfs/README.md
)
## Generate edge list using a R-MAT generator
```
./rmat_edge_generator/generate_edge_list
-o [out edge list file name (required)]
-s [seed for random number generator; default is 123]
-v [SCALE; The logarithm base two of the number of vertices; default is 17]
-e [#of edges; default is 2^{SCALE} x 16]
-a [initiator parameter A; default is 0.57]
-b [initiator parameter B; default is 0.19]
-c [initiator parameter C; default is 0.19]
-r [if true, scrambles edge IDs; default is true]
-u [if true, generates edges for the both direction; default is true]
```
* As for the initiator parameters,
see [Graph500, 3.2 Detailed Text Description](https://graph500.org/?page_id=12#sec-3_2) for more details.
#### Generate Graph 500 inputs
```
./generate_edge_list -o /mnt/ssd/edge_list -v 20 -e $((2**20*16))
````
This command generates a edge list file (/mnt/ssd/edge_list) which contains the edges of a SCALE 20 graph.
In Graph 500, the number of edges of a graph is #vertives x 16 (16 is called 'edge factor').
## Ingest Edge List (construct CSR graph)
```
./ingest_edge_list -g /l/ssd/csr_graph_file /l/ssd/edgelist1 /l/ssd/edgelist2
```
* Load edge data from files /l/ssd/edgelist1 and /l/ssd/edgelist2 (you can specify an arbitrary number of files).
A CSR graph is constructed in /l/ssd/csr_graph_file.
* Each line of input files must be a pair of source and destination vertex IDs (unsigned 64bit number).
* This program treats inputs as a directed graph, that is, it does not ingest edges for both directions.
* This is a multi-threads (OpenMP) program.
You can control the number of threads using the environment variable OMP_NUM_THREADS.
* As for real-world datasets, [SNAP Datasets](http://snap.stanford.edu/data/index.html) is popular in the graph processing community.
Please note that some datasets in SNAP are a little different.
For example, the first line is a comment; you have to delete the line before running this program.
## Run BFS
```
./run_bfs -n \[#of vertices\] -m \[#of edges\] -g \[/path/to/graph_file\]
```
* You can get #of vertices and #of edges by running ingest_edge_list.
* This is a multi-threads (OpenMP) program.
You can control the number of threads using the environment variable OMP_NUM_THREADS.
File rmat_edge_generator.hpp¶
↰ Parent directory (bfs/rmat_edge_generator
)
Definition (bfs/rmat_edge_generator/rmat_edge_generator.hpp
)¶
↰ Return to documentation for file (bfs/rmat_edge_generator/rmat_edge_generator.hpp
)
/*
* Copyright (c) 2013, Lawrence Livermore National Security, LLC.
* Produced at the Lawrence Livermore National Laboratory.
* Written by Roger Pearce <rpearce@llnl.gov>.
* LLNL-CODE-644630.
* All rights reserved.
*
* This file is part of HavoqGT, Version 0.1.
* For details, see https://computation.llnl.gov/casc/dcca-pub/dcca/Downloads.html
*
* Please also read this link – Our Notice and GNU Lesser General Public License.
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (as published by the Free
* Software Foundation) version 2.1 dated February 1999.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the terms and conditions of the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
*
* Our Preamble Notice
*
* A. This notice is required to be provided under our contract with the
* U.S. Department of Energy (DOE). This work was produced at the Lawrence
* Livermore National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE.
*
* B. Neither the United States Government nor Lawrence Livermore National
* Security, LLC nor any of their employees, makes any warranty, express or
* implied, or assumes any liability or responsibility for the accuracy,
* completeness, or usefulness of any information, apparatus, product, or process
* disclosed, or represents that its use would not infringe privately-owned rights.
*
* C. Also, reference herein to any specific commercial products, process, or
* services by trade name, trademark, manufacturer or otherwise does not
* necessarily constitute or imply its endorsement, recommendation, or favoring by
* the United States Government or Lawrence Livermore National Security, LLC. The
* views and opinions of authors expressed herein do not necessarily state or
* reflect those of the United States Government or Lawrence Livermore National
* Security, LLC, and shall not be used for advertising or product endorsement
* purposes.
*
*/
#ifndef BFS_RMAT_EDGE_GENERATOR_HPP
#define BFS_RMAT_EDGE_GENERATOR_HPP
#include <iostream>
#include <random>
#include <cassert>
#include "hash.hpp"
#include <utility>
/// RMAT edge generator, based on Boost Graph's RMAT generator
///
/// Options include scrambling vertices based on a hash funciton, and
/// symmetrizing the list. Generated edges are not sorted. May contain
/// duplicate and self edges.
class rmat_edge_generator {
public:
typedef uint64_t vertex_descriptor;
typedef std::pair<uint64_t, uint64_t> value_type;
typedef value_type edge_type;
///
/// InputIterator class for rmat_edge_generator
class input_iterator_type : public std::iterator<std::input_iterator_tag,
edge_type,
ptrdiff_t,
const edge_type *,
const edge_type &> {
public:
input_iterator_type(rmat_edge_generator *ptr_rmat, uint64_t count)
: m_ptr_rmat(ptr_rmat), m_rng(ptr_rmat->m_seed), m_dis(0.0, 1.0), m_count(count), m_make_undirected(false) {
if (m_count == 0) {
get_next();
m_count = 0; //reset to zero
}
}
const edge_type &operator*() const { return m_current; }
//const uint64_t* operator->() const { return &(operator*()); }
input_iterator_type &operator++() {
get_next();
return *this;
}
input_iterator_type operator++(int) {
input_iterator_type __tmp = *this;
get_next();
return __tmp;
}
edge_type *operator->() {
return &m_current;
}
bool is_equal(const input_iterator_type &_x) const {
return m_count == (_x.m_count);
}
/// Return true if x and y are both end or not end, or x and y are the same.
friend bool
operator==(const input_iterator_type &x, const input_iterator_type &y) { return x.is_equal(y); }
/// Return false if x and y are both end or not end, or x and y are the same.
friend bool
operator!=(const input_iterator_type &x, const input_iterator_type &y) { return !x.is_equal(y); }
private:
input_iterator_type();
void get_next() {
if (m_ptr_rmat->m_undirected && m_make_undirected) {
std::swap(m_current.first, m_current.second);
m_make_undirected = false;
} else {
m_current = m_ptr_rmat->generate_edge(m_rng, m_dis);
++m_count;
m_make_undirected = true;
}
assert(m_current.first <= m_ptr_rmat->max_vertex_id());
assert(m_current.second <= m_ptr_rmat->max_vertex_id());
}
rmat_edge_generator *m_ptr_rmat;
std::mt19937 m_rng;
std::uniform_real_distribution<> m_dis;
uint64_t m_count;
edge_type m_current;
bool m_make_undirected;
};
/// seed used to be 5489
rmat_edge_generator(uint64_t seed, uint64_t vertex_scale,
uint64_t edge_count, double a, double b, double c,
double d, bool scramble, bool undirected)
: m_seed(seed),
m_rng(seed),
m_dis(0.0, 1.0),
m_vertex_scale(vertex_scale),
m_edge_count(edge_count),
m_scramble(scramble),
m_undirected(undirected),
m_rmat_a(a),
m_rmat_b(b),
m_rmat_c(c),
m_rmat_d(d) {
// sanity_max_vertex_id();
// #ifdef DEBUG
// auto itr1 = begin();
// auto itr2 = begin();
// while (itr1 != end()) {
// assert(itr2 != end());
// assert(*itr1 == *itr2);
// assert(itr1 == itr2);
// itr1++;
// itr2++;
// }
// #endif
}
/// Returns the begin of the input iterator
input_iterator_type begin() {
return input_iterator_type(this, 0);
}
/// Returns the end of the input iterator
input_iterator_type end() {
return input_iterator_type(this, m_edge_count);
}
void sanity_max_vertex_id() {
auto itr = begin();
auto itr_end = end();
uint64_t value = 0;
while (itr != itr_end) {
value = std::max(value, (*itr).first);
value = std::max(value, (*itr).second);
}
std::cout << " value: " << value << std::endl;
assert(max_vertex_id() == value);
}
uint64_t max_vertex_id() {
return (uint64_t(1) << uint64_t(m_vertex_scale)) - 1;
}
size_t size() {
return m_edge_count;
}
protected:
/// Generates a new RMAT edge. This function was adapted from the Boost Graph Library.
edge_type generate_edge() {
return generate_edge(m_rng, m_dis);
}
edge_type generate_edge(std::mt19937& rng, std::uniform_real_distribution<> &dis) {
double rmat_a = m_rmat_a;
double rmat_b = m_rmat_b;
double rmat_c = m_rmat_c;
double rmat_d = m_rmat_d;
uint64_t u = 0, v = 0;
uint64_t step = (uint64_t(1) << m_vertex_scale) / 2;
for (unsigned int j = 0; j < m_vertex_scale; ++j) {
double p = dis(rng);
if (p < rmat_a);
else if (p >= rmat_a && p < rmat_a + rmat_b)
v += step;
else if (p >= rmat_a + rmat_b && p < rmat_a + rmat_b + rmat_c)
u += step;
else { // p > a + b + c && p < a + b + c + d
u += step;
v += step;
}
step /= 2;
// 0.2 and 0.9 are hardcoded in the reference SSCA implementation.
// The maximum change in any given value should be less than 10%
rmat_a *= 0.9 + 0.2 * dis(rng);
rmat_b *= 0.9 + 0.2 * dis(rng);
rmat_c *= 0.9 + 0.2 * dis(rng);
rmat_d *= 0.9 + 0.2 * dis(rng);
double S = rmat_a + rmat_b + rmat_c + rmat_d;
rmat_a /= S;
rmat_b /= S;
rmat_c /= S;
// d /= S;
// Ensure all values add up to 1, regardless of floating point errors
rmat_d = 1. - rmat_a - rmat_b - rmat_c;
}
if (m_scramble) {
u = rmat_edge_generator_detail::hash_nbits(u, m_vertex_scale);
v = rmat_edge_generator_detail::hash_nbits(v, m_vertex_scale);
}
return std::make_pair(u, v);
}
const uint64_t m_seed;
std::mt19937 m_rng;
std::uniform_real_distribution<> m_dis;
const uint64_t m_vertex_scale;
const uint64_t m_edge_count;
const bool m_scramble;
const bool m_undirected;
const double m_rmat_a;
const double m_rmat_b;
const double m_rmat_c;
const double m_rmat_d;
};
#endif //BFS_RMAT_EDGE_GENERATOR_HPP
Includes¶
cassert
hash.hpp
(File hash.hpp)iostream
random
(File run_random_vector.cpp)utility
(File bitmap.hpp)
Included By¶
File run_bfs.cpp¶
↰ Parent directory (bfs
)
Definition (bfs/run_bfs.cpp
)¶
↰ Return to documentation for file (bfs/run_bfs.cpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <unistd.h>
#include <iostream>
#include <vector>
#include <tuple>
#include <string>
#include <fstream>
#include "bfs_kernel.hpp"
#include "../utility/bitmap.hpp"
#include "../utility/mmap.hpp"
void parse_options(int argc, char **argv,
size_t &num_vertices, size_t &num_edges,
std::string &graph_file_name) {
num_vertices = 0;
num_edges = 0;
graph_file_name = "";
char c;
while ((c = getopt(argc, argv, "n:m:g:h")) != -1) {
switch (c) {
case 'n': /// Required
num_vertices = std::stoull(optarg);
break;
case 'm': /// Required
num_edges = std::stoull(optarg);
break;
case 'g': /// Required
graph_file_name = optarg;
break;
case 'h':
// usage();
break;
}
}
}
std::pair<uint64_t *, uint64_t *>
map_graph(const size_t num_vertices, const size_t num_edges, const std::string &graph_file_name) {
const size_t graph_size = (num_vertices + 1 + num_edges) * sizeof(uint64_t);
int fd = -1;
void *map_raw_address = nullptr;
std::tie(fd, map_raw_address) = utility::map_file_read_mode(graph_file_name, nullptr, graph_size, 0);
if (fd == -1 || map_raw_address == nullptr) {
std::cerr << "Failed to map the graph" << std::endl;
std::abort();
}
uint64_t *index = static_cast<uint64_t *>(map_raw_address);
const std::ptrdiff_t edges_offset = num_vertices + 1;
uint64_t *edges = static_cast<uint64_t *>(map_raw_address) + edges_offset;
return std::make_pair(index, edges);
}
void find_bfs_root(const size_t num_vertices, const uint64_t *const index, uint16_t *const level) {
for (uint64_t src = 0; src < num_vertices; ++src) {
const size_t degree = index[src + 1] - index[src];
if (degree > 0) {
level[src] = 0;
std::cout << "BFS root: " << src << std::endl;
return;
}
}
std::cerr << "Can not find a proper root vertex; all vertices do not have any edges?" << std::endl;
std::abort();
}
void count_level(const size_t num_vertices, const uint16_t max_level, const uint16_t *const level) {
std::vector<size_t> cnt(max_level + 1, 0);
for (uint64_t i = 0; i < num_vertices; ++i) {
if (level[i] == bfs::k_infinite_level) continue;
if (level[i] > max_level) {
std::cerr << "Invalid level: " << level[i] << " > " << max_level << std::endl;
return;
}
++cnt[level[i]];
}
std::cout << "Level\t#vertices" << std::endl;
for (uint16_t i = 0; i <= max_level; ++i) {
std::cout << i << "\t" << cnt[i] << std::endl;
}
}
int main(int argc, char **argv) {
size_t num_vertices;
size_t num_edges;
std::string graph_file_name;
parse_options(argc, argv, num_vertices, num_edges, graph_file_name);
const uint64_t *index = nullptr;
const uint64_t *edges = nullptr;
std::tie(index, edges) = map_graph(num_vertices, num_edges, graph_file_name);
std::vector<uint16_t> level(num_vertices); // Array to store each vertex's level (a distance from the source vertex)
std::vector<uint64_t> visited_filter(utility::bitmap_size(num_vertices)); // bitmap data to store 'visited' information
bfs::init_bfs(num_vertices, level.data(), visited_filter.data());
find_bfs_root(num_vertices, index, level.data());
const uint16_t max_level = bfs::run_bfs(num_vertices, index, edges, level.data(), visited_filter.data());
count_level(num_vertices, max_level, level.data());
return 0;
}
Includes¶
../utility/bitmap.hpp
../utility/mmap.hpp
bfs_kernel.hpp
(File bfs_kernel.hpp)fstream
iostream
string
tuple
unistd.h
vector
(File run_random_vector.cpp)
File run_random_vector.cpp¶
↰ Parent directory (median_calculation
)
Contents
Definition (median_calculation/run_random_vector.cpp
)¶
↰ Return to documentation for file (median_calculation/run_random_vector.cpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>
#include <cassert>
#include <cstdlib>
#ifdef _OPENMP
#include <omp.h>
#endif
#include "../utility/commandline.hpp"
#include "../utility/umap_fits_file.hpp"
#include "torben.hpp"
#include "utility.hpp"
#include "vector.hpp"
#include "../utility/time.hpp"
using pixel_type = float;
constexpr size_t default_num_random_vector = 100000;
class beta_distribution {
public:
beta_distribution(double a, double b)
: m_x_gamma(a, 1.0),
m_y_gamma(b, 1.0) {}
template <typename rnd_engine>
double operator()(rnd_engine &engine) {
double x = m_x_gamma(engine);
double y = m_y_gamma(engine);
return x / (x + y);
}
private:
std::gamma_distribution<> m_x_gamma;
std::gamma_distribution<> m_y_gamma;
};
std::pair<double, std::vector<std::pair<pixel_type, vector_t>>>
shoot_vector(const median::cube_t<pixel_type> &cube, const std::size_t num_random_vector) {
// Array to store results of the median calculation
std::vector<std::pair<pixel_type, vector_t>> result(num_random_vector);
double total_execution_time = 0.0;
#ifdef _OPENMP
#pragma omp parallel
#endif
{
#ifdef _OPENMP
std::mt19937 rnd_engine(123 + omp_get_thread_num());
#else
std::mt19937 rnd_engine(123);
#endif
std::uniform_int_distribution<int> x_start_dist(0.2 * cube.size_x, 0.8 * cube.size_x);
std::uniform_int_distribution<int> y_start_dist(0.2 * cube.size_y, 0.8 * cube.size_y);
beta_distribution x_beta_dist(3, 2);
beta_distribution y_beta_dist(3, 2);
std::discrete_distribution<int> plus_or_minus{-1, 1};
// Shoot random vectors using multiple threads
#ifdef _OPENMP
#pragma omp for
#endif
for (int i = 0; i < num_random_vector; ++i) {
double x_intercept = x_start_dist(rnd_engine);
double y_intercept = y_start_dist(rnd_engine);
// Changed to the const value to 2 from 25 so that vectors won't access
// out of range of the cube with a large number of frames
//
// This is a temporary measures
double x_slope = x_beta_dist(rnd_engine) * plus_or_minus(rnd_engine) * 2;
double y_slope = y_beta_dist(rnd_engine) * plus_or_minus(rnd_engine) * 2;
vector_t vector{x_intercept, x_slope, y_intercept, y_slope};
vector_iterator<pixel_type> begin(cube, vector, 0);
vector_iterator<pixel_type> end(vector_iterator<pixel_type>::create_end(cube, vector));
// median calculation using Torben algorithm
const auto start = utility::elapsed_time_sec();
result[i].first = torben(begin, end);
total_execution_time += utility::elapsed_time_sec(start);
result[i].second = vector;
}
}
return std::make_pair(total_execution_time, result);
}
void print_top_median(const median::cube_t<pixel_type> &cube, std::vector<std::pair<pixel_type, vector_t>> &result) {
// Sort the results by the descending order of median value
std::partial_sort(result.begin(),
result.begin() + 10, // get only top 10 elements
result.end(),
[](const std::pair<pixel_type, vector_t> &lhd,
const std::pair<pixel_type, vector_t> &rhd) {
return (lhd.first > rhd.first);
});
// Print out the top 10 median values and corresponding pixel values
std::cout << "Top 10 median and corresponding pixel values (NaN values are not used in median calculation)"
<< std::endl;
std::cout.setf(std::ios::fixed, std::ios::floatfield);
std::cout.precision(2);
for (size_t i = 0; i < 10; ++i) {
const pixel_type median = result[i].first;
const vector_t vector = result[i].second;
std::cout << "[" << i << "]"
<< "\n Median: " << median
<< "\n Vector: " << vector.x_slope << " " << vector.x_intercept
<< " " << vector.y_slope << " " << vector.y_intercept << std::endl;
for (size_t k = 0; k < cube.size_k; ++k) {
const ssize_t index = get_index(cube, vector, k);
if (index == -1) continue;
const pixel_type value = median::reverse_byte_order(cube.data[index]);
if (median::is_nan(value))
std::cout << " 'NaN'";
else
std::cout << " " << median::reverse_byte_order(cube.data[index]);
}
std::cout << std::endl;
}
}
int main(int argc, char **argv) {
utility::umt_optstruct_t options;
umt_getoptions(&options, argc, argv);
#ifdef _OPENMP
omp_set_num_threads(options.numthreads);
#endif
size_t BytesPerElement;
median::cube_t<pixel_type> cube;
// Alloc memory space and read data from fits files with umap
cube.data = (pixel_type *)utility::umap_fits_file::PerFits_alloc_cube(
options.filename, &BytesPerElement, &cube.size_x, &cube.size_y, &cube.size_k);
if (cube.data == nullptr) {
std::cerr << "Failed to allocate memory for cube\n";
std::abort();
}
if (sizeof(pixel_type) != BytesPerElement) {
std::cerr << "Wrong pixel type" << std::endl;
std::abort();
}
const char* buf = std::getenv("NUM_VECTORS");
std::size_t num_random_vector = default_num_random_vector;
if (buf != nullptr) {
num_random_vector = std::stoll(buf);
}
auto result = shoot_vector(cube, num_random_vector);
std::cout << "#of vectors = " << num_random_vector
<< "\nexecution time (sec) = " << result.first
<< "\nvectors/sec = " << static_cast<double>(num_random_vector) / result.first << std::endl;
print_top_median(cube, result.second);
utility::umap_fits_file::PerFits_free_cube(cube.data);
return 0;
}
Includes¶
../utility/commandline.hpp
../utility/time.hpp
../utility/umap_fits_file.hpp
algorithm
cassert
cstdlib
iostream
random
(File run_random_vector.cpp)torben.hpp
(File torben.hpp)utility.hpp
(File utility.hpp)vector
(File run_random_vector.cpp)vector.hpp
(File vector.hpp)
Classes¶
Typedefs¶
Variables¶
File test_bfs.cpp¶
↰ Parent directory (bfs
)
Definition (bfs/test_bfs.cpp
)¶
↰ Return to documentation for file (bfs/test_bfs.cpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <unistd.h>
#include <iostream>
#include <vector>
#include <tuple>
#include <string>
#include <fstream>
#include "bfs_kernel.hpp"
#include "../utility/bitmap.hpp"
#include "../utility/mmap.hpp"
void parse_options(int argc, char **argv,
size_t &num_vertices, size_t &num_edges,
std::string &graph_file_name,
std::string &bfs_level_reference_file_name) {
num_vertices = 0;
num_edges = 0;
graph_file_name = "";
bfs_level_reference_file_name = "";
char c;
while ((c = getopt(argc, argv, "n:m:g:l:h")) != -1) {
switch (c) {
case 'n': /// Required
num_vertices = std::stoull(optarg);
break;
case 'm': /// Required
num_edges = std::stoull(optarg);
break;
case 'g': /// Required
graph_file_name = optarg;
break;
case 'l': /// Required
bfs_level_reference_file_name = optarg;
break;
case 'h':
// usage();
break;
}
}
}
std::pair<uint64_t *, uint64_t *>
map_graph(const size_t num_vertices, const size_t num_edges, const std::string &graph_file_name) {
const size_t graph_size = (num_vertices + 1 + num_edges) * sizeof(uint64_t);
int fd = -1;
void *map_raw_address = nullptr;
std::tie(fd, map_raw_address) = utility::map_file_read_mode(graph_file_name, nullptr, graph_size, 0);
if (fd == -1 || map_raw_address == nullptr) {
std::cerr << "Failed to map the graph" << std::endl;
std::abort();
}
uint64_t *index = static_cast<uint64_t *>(map_raw_address);
const std::ptrdiff_t edges_offset = num_vertices + 1;
uint64_t *edges = static_cast<uint64_t *>(map_raw_address) + edges_offset;
return std::make_pair(index, edges);
}
void validate_level(const std::vector<uint16_t>& level, const std::string& bfs_level_reference_file_name) {
std::ifstream ifs(bfs_level_reference_file_name);
if (!ifs.is_open()) {
std::cerr << "Can not open: "<< bfs_level_reference_file_name << std::endl;
std::abort();
}
std::vector<uint16_t> ref_level(level.size(), bfs::k_infinite_level);
uint64_t id;
uint16_t lv;
while (ifs >> id >> lv) {
ref_level[id] = lv;
}
if (level != ref_level) {
std::cerr << "BFS level is wrong" << std::endl;
std::abort();
}
}
int main(int argc, char **argv) {
size_t num_vertices;
size_t num_edges;
std::string graph_file_name;
std::string bfs_level_reference_file_name;
parse_options(argc, argv, num_vertices, num_edges, graph_file_name, bfs_level_reference_file_name);
const uint64_t *index = nullptr;
const uint64_t *edges = nullptr;
std::tie(index, edges) = map_graph(num_vertices, num_edges, graph_file_name);
std::vector<uint16_t> level(num_vertices); // Array to store each vertex's level (a distance from the source vertex)
std::vector<uint64_t> visited_filter(utility::bitmap_size(num_vertices)); // bitmap data to store 'visited' information
bfs::init_bfs(num_vertices, level.data(), visited_filter.data());
level[0] = 0; // Start from vertex 0
bfs::run_bfs(num_vertices, index, edges, level.data(), visited_filter.data());
std::cout << "Finished BFS" << std::endl;
validate_level(level, bfs_level_reference_file_name);
std::cout << "Passed validation" << std::endl;
return 0;
}
Includes¶
../utility/bitmap.hpp
../utility/mmap.hpp
bfs_kernel.hpp
(File bfs_kernel.hpp)fstream
iostream
string
tuple
unistd.h
vector
(File run_random_vector.cpp)
File test_median_calculation.cpp¶
↰ Parent directory (median_calculation
)
Contents
Definition (median_calculation/test_median_calculation.cpp
)¶
↰ Return to documentation for file (median_calculation/test_median_calculation.cpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <iostream>
#include <cmath>
#include "torben.hpp"
#include "utility.hpp"
#include "vector.hpp"
#include "../utility/commandline.hpp"
#include "../utility/umap_fits_file.hpp"
using pixel_type = float;
constexpr size_t num_vectors = 6;
const pixel_type x_intercept[num_vectors] = {1058.2, 1325.606, 1010.564, 829.674, 1390.826, 1091.015};
const pixel_type x_slope[num_vectors] = {3.5, 3.5, 3.5, 3.5, 3.5, 3.5};
const pixel_type y_intercept[num_vectors] = {124, 424, 724, 1024, 1324, 1624};
const pixel_type y_slope[num_vectors] = {0, 0, 0, 0, 0, 0};
const pixel_type correct_median[num_vectors] = {14913.25, 15223.21, 2284.29, 8939.15, 24899.55, 2395.80};
int main(int argc, char** argv)
{
utility::umt_optstruct_t options;
umt_getoptions(&options, argc, argv);
size_t BytesPerElement;
median::cube_t<float> cube;
cube.data = (float*)utility::umap_fits_file::PerFits_alloc_cube(
options.filename, &BytesPerElement, &cube.size_x, &cube.size_y, &cube.size_k);
for (int i = 0; i < num_vectors; ++i) {
std::cout << "Vector " << i << std::endl;
vector_t vector{x_intercept[i], x_slope[i], y_intercept[i], y_slope[i]};
vector_iterator<pixel_type> begin(cube, vector, 0);
vector_iterator<pixel_type> end(vector_iterator<pixel_type>::create_end(cube, vector));
// median calculation w/ Torben algorithm
const auto median_val = torben(begin, end);
// Check the result
std::cout.setf(std::ios::fixed, std::ios::floatfield);
std::cout.precision(2);
if (std::fabs(median_val - correct_median[i]) < 0.01) {
std::cout << " Correct " << median_val << " == " << correct_median[i] << std::endl;
} else {
std::cerr << " Error " << median_val << " != " << correct_median[i] << std::endl;
std::abort();
}
}
utility::umap_fits_file::PerFits_free_cube(cube.data);
std::cout << "Passed all tests" << std::endl;
return 0;
}
Includes¶
../utility/commandline.hpp
../utility/umap_fits_file.hpp
cmath
iostream
torben.hpp
(File torben.hpp)utility.hpp
(File utility.hpp)vector.hpp
(File vector.hpp)
Functions¶
Typedefs¶
File time.hpp¶
↰ Parent directory (utility
)
Definition (utility/time.hpp
)¶
↰ Return to documentation for file (utility/time.hpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UMAP_TEST_LIB_UTILITY_TIME_HPP
#define UMAP_TEST_LIB_UTILITY_TIME_HPP
#include <chrono>
namespace utility {
inline std::chrono::high_resolution_clock::time_point elapsed_time_sec() {
return std::chrono::high_resolution_clock::now();
}
inline double elapsed_time_sec(const std::chrono::high_resolution_clock::time_point &tic) {
auto duration_time = std::chrono::high_resolution_clock::now() - tic;
return static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(duration_time).count() / 1e6);
}
}
#endif //UMAP_TEST_LIB_UTILITY_TIME_HPP
Includes¶
chrono
Included By¶
Namespaces¶
File torben.hpp¶
↰ Parent directory (median_calculation
)
Definition (median_calculation/torben.hpp
)¶
↰ Return to documentation for file (median_calculation/torben.hpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
The original code of Torben algorithm is in public domain
Its algorithm is developed by Torben Mogensen and implementated by N. Devillard
This version considerably modified
This implementation also contains the modification proposed in https://github.com/sarnold/medians-1D/issues/8
*/
#ifndef UMAP_TORBEN_HPP
#define UMAP_TORBEN_HPP
#include <algorithm>
#include <iterator>
/*
STL-like Torben algorithm implementation for median calculation
Returns the median value of given elements that are accessible via a random access iterator
\tparam iterator_type Type of the iterator
\param iterator_begin Iterator for the beginning position
\param iterator_end Iterator for the end position
\return Calculated median value. If the size of the array is 0, returns 0.
\example
1) STL container
std::vector<int> vec;
int median = torben(vec.cbegin(), vec.cend());
2) you can also use a normal array
int array[10];
int median = torben(array, array + 10);
3) use your own iterator
own_iterator_class itr_begin;
own_iterator_class itr_end;
int median = torben(itr_begin, itr_end);
class vector_iterator {
public:
// Required types to use some stl functions
using value_type = pixel_type;
using difference_type = ssize_t;
using iterator_category = std::random_access_iterator_tag;
using pointer = value_type *;
using reference = value_type &;
// Constructor
vector_iterator(const median::cube_t<pixel_type> &_cube,
const median::vector_t &_vector,
const size_t _start_pos)
: cube(_cube),
vector(_vector),
current_pos(_start_pos) {}
// Copy constructor
vector_iterator(const vector_iterator&) = default;
bool operator!=(const vector_iterator &);
difference_type operator-(const vector_iterator &);
value_type operator*();
value_type operator[](size_t);
// To support
// ++iterator
value_type operator++() {
size_t tmp = current_pos;
++current_pos;
return (*this)[tmp];
}
median::cube_t<pixel_type> cube;
median::vector_t vector;
size_t current_pos;
};
*/
template <typename iterator_type>
typename iterator_type::value_type
torben(iterator_type iterator_begin, iterator_type iterator_end) {
using value_type = typename std::iterator_traits<iterator_type>::value_type;
if (iterator_begin == iterator_end)
return 0;
// ---------- Find min and max value over time frame ---------- //
value_type min = *iterator_begin;
value_type max = *iterator_begin;
std::size_t length = 0;
for (auto iterator(iterator_begin); iterator != iterator_end; ++iterator) {
const value_type value = *iterator;
min = std::min(min, value);
max = std::max(max, value);
++length;
}
const size_t half = (length + 1) / 2;
// ---------- Find median value ---------- //
size_t less, greater, equal;
value_type guess, maxltguess, mingtguess;
while (true) {
guess = (min + max) / 2.0; // Should cast to double before divide?
less = 0;
greater = 0;
equal = 0;
maxltguess = min;
mingtguess = max;
for (auto iterator(iterator_begin); iterator != iterator_end; ++iterator) {
const value_type value = *iterator;
if (value < guess) {
less++;
if (value > maxltguess) maxltguess = value;
} else if (value > guess) {
greater++;
if (value < mingtguess) mingtguess = value;
} else {
equal++;
}
}
if (less <= half && greater <= half) break;
else if (less > greater) max = maxltguess;
else min = mingtguess;
}
// ----- Calculate a mean value if the number of the given elements is an even number ----- //
if (less >= half) min = maxltguess;
else if (less + equal >= half) min = guess;
else min = mingtguess;
if (length & 1) return min;
if (greater >= half) max = mingtguess;
else if (greater + equal >= half) max = guess;
else max = maxltguess;
return (min + max) / 2.0;
}
#endif //UMAP_TORBEN_HPP
Includes¶
algorithm
iterator
Functions¶
File umap_file.hpp¶
↰ Parent directory (utility
)
Definition (utility/umap_file.hpp
)¶
↰ Return to documentation for file (utility/umap_file.hpp
)
/* This file is part of UMAP. For copyright information see the COPYRIGHT
* file in the top level directory, or at
* https://github.com/LLNL/umap/blob/master/COPYRIGHT This program is free
* software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License (as published by the Free Software
* Foundation) version 2.1 dated February 1999. This program is distributed in
* the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the terms and conditions of the GNU Lesser General Public License for
* more details. You should have received a copy of the GNU Lesser General
* Public License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _UMAP_FILE_HPP_
#define _UMAP_FILE_HPP_
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <iostream>
#include <string>
#include <sstream>
#include <sys/stat.h>
#include <fcntl.h>
#include "umap/umap.h"
namespace utility {
void* map_in_file(
std::string filename,
bool initonly,
bool noinit,
bool usemmap,
uint64_t numbytes)
{
int o_opts = O_RDWR | O_LARGEFILE | O_DIRECT;
void* region = NULL;
int fd;
if ( initonly || !noinit ) {
o_opts |= O_CREAT;
unlink(filename.c_str()); // Remove the file if it exists
}
if ( ( fd = open(filename.c_str(), o_opts, S_IRUSR | S_IWUSR) ) == -1 ) {
std::string estr = "Failed to open/create " + filename + ": ";
perror(estr.c_str());
return NULL;
}
if ( o_opts & O_CREAT ) {
// If we are initializing, attempt to pre-allocate disk space for the file.
try {
int x;
if ( ( x = posix_fallocate(fd, 0, numbytes) != 0 ) ) {
std::ostringstream ss;
ss << "Failed to pre-allocate " <<
numbytes << " bytes in " << filename << ": ";
perror(ss.str().c_str());
return NULL;
}
} catch(const std::exception& e) {
std::cerr << "posix_fallocate: " << e.what() << std::endl;
return NULL;
} catch(...) {
std::cerr << "posix_fallocate failed to allocate backing store\n";
return NULL;
}
}
struct stat sbuf;
if (fstat(fd, &sbuf) == -1) {
std::string estr = "Failed to get status (fstat) for " + filename + ": ";
perror(estr.c_str());
return NULL;
}
if ( (off_t)sbuf.st_size != (numbytes) ) {
std::cerr << filename << " size " << sbuf.st_size
<< " does not match specified data size of " << (numbytes) << std::endl;
return NULL;
}
const int prot = PROT_READ|PROT_WRITE;
if ( usemmap ) {
region = mmap(NULL, numbytes, prot, MAP_SHARED | MAP_NORESERVE, fd, 0);
if (region == MAP_FAILED) {
std::ostringstream ss;
ss << "mmap of " << numbytes << " bytes failed for " << filename << ": ";
perror(ss.str().c_str());
return NULL;
}
}
else {
int flags = UMAP_PRIVATE;
region = umap(NULL, numbytes, prot, flags, fd, 0);
if ( region == UMAP_FAILED ) {
std::ostringstream ss;
ss << "umap_mf of " << numbytes
<< " bytes failed for " << filename << ": ";
perror(ss.str().c_str());
return NULL;
}
}
return region;
}
void unmap_file(bool usemmap, uint64_t numbytes, void* region)
{
if ( usemmap ) {
if ( munmap(region, numbytes) < 0 ) {
std::ostringstream ss;
ss << "munmap failure: ";
perror(ss.str().c_str());
exit(-1);
}
}
else {
if (uunmap(region, numbytes) < 0) {
std::ostringstream ss;
ss << "uunmap of failure: ";
perror(ss.str().c_str());
exit(-1);
}
}
}
}
#endif
Includes¶
fcntl.h
iostream
sstream
string
sys/stat.h
umap/umap.h
Namespaces¶
Defines¶
File umap_fits_file.hpp¶
↰ Parent directory (utility
)
Contents
Definition (utility/umap_fits_file.hpp
)¶
↰ Return to documentation for file (utility/umap_fits_file.hpp
)
/*
* This file is part of UMAP.
*
* For copyright information see the COPYRIGHT file in the top level
* directory or at https://github.com/LLNL/umap/blob/master/COPYRIGHT.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License (as published by
* the Free Software Foundation) version 2.1 dated February 1999.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the terms and conditions of the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*/
#ifndef _UMAP_PERFITS_H
#define _UMAP_PERFITS_H
#include <ostream>
#include <string>
#include <vector>
#include <stdint.h>
#include <iomanip>
#include <sstream>
#include <cassert>
#include <unordered_map>
#include <algorithm>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include "umap/umap.h"
#include "fitsio.h"
#include "../utility/commandline.hpp"
#include "umap/Store.h"
namespace utility {
namespace umap_fits_file {
struct Tile_Dim {
std::size_t xDim;
std::size_t yDim;
std::size_t elem_size;
};
struct Tile_File {
int fd;
std::string fname;
std::size_t tile_start;
std::size_t tile_size;
};
class Tile {
friend std::ostream &operator<<(std::ostream &os, utility::umap_fits_file::Tile const &ft);
public:
Tile(const std::string& _fn);
ssize_t pread(std::size_t alignment, void* cpy_buf, void* buf, std::size_t nbytes, off_t offset);
Tile_Dim get_Dim() { return dim; }
private:
Tile_File file;
Tile_Dim dim;
};
std::ostream &operator<<(std::ostream &os, utility::umap_fits_file::Tile const &ft);
struct Cube {
size_t tile_size; // Size of each tile (assumed to be the same for each tile)
size_t cube_size; // Total bytes in cube
off_t page_size;
vector<utility::umap_fits_file::Tile> tiles; // Just one column for now
};
static std::unordered_map<void*, Cube*> Cubes;
class CfitsStoreFile : public Store {
public:
CfitsStoreFile(Cube* _cube_, size_t _rsize_, size_t _alignsize_)
: cube{_cube_}, rsize{_rsize_}, alignsize{_alignsize_}
{
if ( posix_memalign(&alignment_buffer, alignsize, alignsize) ) {
exit(1);
}
}
~CfitsStoreFile() {
free(alignment_buffer);
}
ssize_t read_from_store(char* buf, size_t nb, off_t off) {
ssize_t rval;
ssize_t bytesread = 0;
//
// Now read in remaining bytes
//
while ( nb ) {
off_t tileno = off / cube->tile_size;
off_t tileoffset = off % cube->tile_size;
size_t bytes_to_eof = cube->tile_size - tileoffset;
size_t bytes_to_read = std::min(bytes_to_eof, nb);
if ( ( rval = cube->tiles[tileno].pread(cube->page_size, alignment_buffer, buf, bytes_to_read, tileoffset) ) == -1) {
perror("ERROR: pread failed");
exit(1);
}
bytesread += rval;
nb -= rval;
buf += rval;
off += rval;
}
return bytesread;
}
ssize_t write_to_store(char* buf, size_t nb, off_t off) {
assert("FITS write not supported" && 0);
return 0;
}
void* region;
private:
Cube* cube;
void* alignment_buffer;
size_t rsize;
size_t alignsize;
int fd;
};
/* Returns pointer to cube[Z][Y][X] Z=time, X/Y=2D space coordinates */
void* PerFits_alloc_cube(
string name,
size_t* BytesPerElement, /* Output: size of each element of cube */
size_t* xDim, /* Output: Dimension of X */
size_t* yDim, /* Output: Dimension of Y */
size_t* zDim /* Output: Dimension of Z */
)
{
void* region = NULL;
Cube* cube = new Cube{.tile_size = 0, .cube_size = 0};
cube->page_size = utility::umt_getpagesize();
string basename(name);
*xDim = *yDim = *BytesPerElement = 0;
for (int i = 1; ; ++i) {
std::stringstream ss;
ss << basename << i << ".fits";
struct stat sbuf;
if ( stat(ss.str().c_str(), &sbuf) == -1 ) {
if ( i == 1 ) {
cerr << "File: " << ss.str() << " does not exist\n";
return region;
}
break;
}
utility::umap_fits_file::Tile T( ss.str() );
ss.str(""); ss.clear();
ss << T << endl;
utility::umap_fits_file::Tile_Dim dim = T.get_Dim();
if ( *BytesPerElement == 0 ) {
*xDim = dim.xDim;
*yDim = dim.yDim;
*BytesPerElement = dim.elem_size;
cube->tile_size = (dim.xDim * dim.yDim * dim.elem_size);
}
else {
assert( *xDim == dim.xDim && *yDim == dim.yDim && *BytesPerElement == dim.elem_size );
}
*zDim = i;
cube->cube_size += cube->tile_size;
cube->tiles.push_back(T);
}
// Make sure that our cube is padded if necessary to be page aligned
size_t psize = utility::umt_getpagesize();
long remainder = cube->cube_size % psize;
cube->cube_size += remainder ? (psize - remainder) : 0;
CfitsStoreFile* cstore;
cstore = new CfitsStoreFile{cube, cube->cube_size, psize};
const int prot = PROT_READ|PROT_WRITE;
int flags = UMAP_PRIVATE;
cstore->region = umap_ex(NULL, cube->cube_size, prot, flags, 0, 0, cstore);
if ( cstore->region == UMAP_FAILED ) {
ostringstream ss;
ss << "umap of " << cube->cube_size << " bytes failed for Cube";
perror(ss.str().c_str());
return NULL;
}
Cubes[cstore->region] = cube;
return cstore->region;
}
void PerFits_free_cube(void* region)
{
auto it = Cubes.find(region);
assert( "free_cube: failed to find control object" && it != Cubes.end() );
Cube* cube = it->second;
if (uunmap(region, cube->cube_size) < 0) {
ostringstream ss;
ss << "uunmap of " << cube->cube_size << " bytes failed on region " << region << ": ";
perror(ss.str().c_str());
exit(-1);
}
delete cube;
Cubes.erase(region);
}
Tile::Tile(const std::string& _fn)
{
fitsfile* fptr = NULL;
int status = 0;
LONGLONG headstart;
LONGLONG datastart;
LONGLONG dataend;
int bitpix;
long naxis[2];
int naxes;
int open_flags = (O_RDONLY | O_LARGEFILE | O_DIRECT);
file.fname = _fn;
file.tile_start = (size_t)0;
file.tile_size = (size_t)0;
dim.xDim = (size_t)0;
dim.yDim = (size_t)0;
dim.elem_size = 0;
file.fd = -1;
if ( fits_open_data(&fptr, file.fname.c_str(), READONLY, &status) ) {
fits_report_error(stderr, status);
exit(-1);
}
if ( fits_get_hduaddrll(fptr, &headstart, &datastart, &dataend, &status) ) {
fits_report_error(stderr, status);
exit(-1);
}
if ( fits_get_img_type(fptr, &bitpix, &status) ) {
fits_report_error(stderr, status);
exit(-1);
}
if ( fits_get_img_param(fptr, 2, &bitpix, &naxes, &naxis[0], &status) ) {
fits_report_error(stderr, status);
exit(-1);
}
if ( fits_close_file(fptr, &status) ) {
fits_report_error(stderr, status);
exit(-1);
}
if ( ( file.fd = open(file.fname.c_str(), open_flags) ) == -1 ) {
perror(file.fname.c_str());
exit(-1);
}
dim.xDim = (size_t)naxis[0];
dim.yDim = (size_t)naxis[1];
dim.elem_size = bitpix < 0 ? (size_t)( ( bitpix * -1 ) / 8 ) : (size_t)( bitpix / 8 );
file.tile_start = (size_t)datastart;
file.tile_size = (size_t)(dim.xDim * dim.yDim * dim.elem_size);
assert( (dataend - datastart) >= (dim.xDim * dim.yDim * dim.elem_size) );
}
ssize_t Tile::pread(std::size_t alignment, void* cpy_buf, void* buf, std::size_t nbytes, off_t offset)
{
std::size_t rval;
offset += file.tile_start; // Skip to data portion of file
off_t unaligned_amount = offset & (alignment - 1);
offset -= unaligned_amount;
char* tbuf = (char*)cpy_buf;
if ( ( rval = ::pread(file.fd, tbuf, alignment, offset) ) == -1) {
perror("ERROR: pread failed");
exit(1);
}
ssize_t amount_to_copy = std::min(rval, nbytes) - unaligned_amount;
memcpy(buf, &tbuf[unaligned_amount], amount_to_copy);
return amount_to_copy;
}
std::ostream &operator<<(std::ostream &os, Tile const &ft)
{
os << ft.file.fname << " "
<< "Start=" << ft.file.tile_start << ", "
<< "Size=" << ft.file.tile_size << ", "
<< "XDim=" << ft.dim.xDim << ", "
<< "YDim=" << ft.dim.yDim << ", "
<< "ESize=" << ft.dim.elem_size << " ";
return os;
}
}
}
#endif
Includes¶
../utility/commandline.hpp
algorithm
cassert
fcntl.h
fitsio.h
iomanip
ostream
sstream
stdint.h
stdlib.h
string
string.h
sys/stat.h
sys/types.h
umap/Store.h
umap/umap.h
unistd.h
unordered_map
vector
(File run_random_vector.cpp)
Functions¶
Variables¶
File umapcpu.cpp¶
↰ Parent directory (umapcpu
)
Definition (umapcpu/umapcpu.cpp
)¶
↰ Return to documentation for file (umapcpu/umapcpu.cpp
)
/*
* This file is part of UMAP. For copyright information see the COPYRIGHT file
* in the top level directory, or at
* https://github.com/LLNL/umap/blob/master/COPYRIGHT This program is free
* software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License (as published by the Free Software
* Foundation) version 2.1 dated February 1999. This program is distributed in
* the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the terms and conditions of the GNU Lesser General Public License for more
* details. You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#include <iostream>
#include <random>
#include <algorithm>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h> // optind
#include <errno.h>
#include <utmpx.h>
#include <parallel/algorithm>
#ifdef _OPENMP
#include <omp.h>
#endif
#include "umap/umap.h"
#include "../utility/commandline.hpp"
#include "../utility/umap_file.hpp"
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
void cpu_setcpu(int cpu)
{
int s;
cpu_set_t cpuset;
pthread_t thread;
thread = pthread_self();
CPU_ZERO(&cpuset);
CPU_SET(cpu, &cpuset);
s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (s != 0)
handle_error_en(s, "pthread_setaffinity_np");
/* Check the actual affinity mask assigned to the thread */
s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (s != 0)
handle_error_en(s, "pthread_getaffinity_np");
}
static inline uint64_t getns(void)
{
struct timespec ts;
int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
assert(ret == 0);
return (((uint64_t)ts.tv_sec) * 1000000000ULL) + ts.tv_nsec;
}
void initdata(uint64_t *region, int64_t rlen) {
fprintf(stdout, "initdata: %p, %ld\n", region, rlen);
#pragma omp parallel for
for(int64_t i=0; i< rlen; ++i) {
region[i] = (uint64_t) (rlen - i);
}
}
int main(int argc, char **argv)
{
utility::umt_optstruct_t options;
long pagesize;
int64_t totalbytes;
uint64_t arraysize;
void* base_addr;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> rnd_int(0, 39);
pagesize = utility::umt_getpagesize();
umt_getoptions(&options, argc, argv);
omp_set_num_threads(options.numthreads);
totalbytes = options.numpages*pagesize;
base_addr = utility::map_in_file(options.filename, options.initonly,
options.noinit, options.usemmap, totalbytes);
assert(base_addr != NULL);
fprintf(stdout, "%lu pages, %lu threads\n", options.numpages, options.numthreads);
uint64_t *arr = (uint64_t *) base_addr;
arraysize = totalbytes/sizeof(int64_t);
uint64_t start = getns();
if ( !options.noinit ) {
// init data
initdata(arr, arraysize);
fprintf(stdout, "Init took %f us\n", (double)(getns() - start)/1000000.0);
}
const int testpages = 400;
if ( !options.initonly )
{
std::vector<int> cpus{0, 10, 20, 30};
start = getns();
#pragma omp parallel for
for (uint64_t page = 0; page < options.numpages - testpages; page += testpages) {
uint64_t sum = 0;
//cpu_setcpu(10);
for (int x = 0; x < testpages; x++) {
uint64_t* p = &arr[(page+x)*(pagesize/sizeof(uint64_t*))];
sum += *p;
}
cpu_setcpu(rnd_int(gen));
//cpu_setcpu(30);
for (int x = 0; x < testpages; ++x) {
uint64_t* p = &arr[(page+x)*(pagesize/sizeof(uint64_t*))];
*p = sum;
}
}
fprintf(stdout, "test took %f us\n", (double)(getns() - start)/1000000.0);
}
utility::unmap_file(options.usemmap, totalbytes, base_addr);
return 0;
}
Includes¶
../utility/commandline.hpp
../utility/umap_file.hpp
algorithm
assert.h
errno.h
fcntl.h
iostream
parallel/algorithm
pthread.h
random
(File run_random_vector.cpp)stdint.h
stdio.h
stdlib.h
string.h
sys/ioctl.h
sys/mman.h
sys/stat.h
sys/time.h
sys/types.h
umap/umap.h
unistd.h
utmpx.h
Functions¶
File umapsort.cpp¶
↰ Parent directory (umapsort
)
Definition (umapsort/umapsort.cpp
)¶
↰ Return to documentation for file (umapsort/umapsort.cpp
)
/* This file is part of UMAP. For copyright information see the COPYRIGHT
* file in the top level directory, or at
* https://github.com/LLNL/umap/blob/master/COPYRIGHT. This program is free
* software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License (as published by the Free Software
* Foundation) version 2.1 dated February 1999. This program is distributed in
* the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the terms and conditions of the GNU Lesser General Public License for
* more details. You should have received a copy of the GNU Lesser General
* Public License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#include <iostream>
#include <string>
#include <sstream>
#include <cassert>
#include <random>
#include <string>
#include <vector>
#include <parallel/algorithm>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <omp.h>
#include "umap/umap.h"
#include "../utility/commandline.hpp"
#include "../utility/umap_file.hpp"
using namespace std;
bool sort_ascending = true;
static inline uint64_t getns(void)
{
struct timespec ts;
int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
assert(ret == 0);
return (((uint64_t)ts.tv_sec) * 1000000000ULL) + ts.tv_nsec;
}
void initdata(uint64_t *region, uint64_t rlen) {
fprintf(stdout, "initdata: %p, %llu\n", region, rlen);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<uint64_t> rnd_int;
#pragma omp parallel for
for(uint64_t i=0; i < rlen; ++i) {
region[i] = (uint64_t) (rlen - i);
}
}
void validatedata(uint64_t *region, uint64_t rlen) {
if (sort_ascending == true) {
#pragma omp parallel for
for(uint64_t i = 0; i < rlen; ++i) {
if (region[i] != (i+1)) {
fprintf(stderr, "Worker %d found an error at index %lu, %lu != lt %lu!\n",
omp_get_thread_num(), i, region[i], i+1);
if (i < 3) {
fprintf(stderr, "Context ");
for (int j=0; j < 7; j++) {
fprintf(stderr, "%lu ", region[j]);
}
fprintf(stderr, "\n");
}
else if (i > (rlen-4)) {
fprintf(stderr, "Context ");
for (uint64_t j=rlen-8; j < rlen; j++) {
fprintf(stderr, "%lu ", region[j]);
}
fprintf(stderr, "\n");
}
else {
fprintf(stderr,
"Context i-3 i-2 i-1 i i+1 i+2 i+3:%lu %lu %lu %lu %lu %lu %lu\n",
region[i-3], region[i-2], region[i-1], region[i], region[i+1], region[i+2], region[i+3]);
}
}
}
}
else {
#pragma omp parallel for
for(uint64_t i = 0; i < rlen; ++i) {
if(region[i] != (rlen - i)) {
fprintf(stderr, "Worker %d found an error at index %lu, %lu != %lu!\n",
omp_get_thread_num(), i, region[i], (rlen - i));
if (i < 3) {
fprintf(stderr, "Context ");
for (int j=0; j < 7; j++) {
fprintf(stderr, "%lu ", region[j]);
}
fprintf(stderr, "\n");
}
else if (i > (rlen-4)) {
fprintf(stderr, "Context ");
for (uint64_t j=rlen-8; j < rlen; j++) {
fprintf(stderr, "%lu ", region[j]);
}
fprintf(stderr, "\n");
}
else {
fprintf(stderr,
"Context i-3 i-2 i-1 i i+1 i+2 i+3:%lu %lu %lu %lu %lu %lu %lu\n",
region[i-3], region[i-2], region[i-1], region[i], region[i+1], region[i+2], region[i+3]);
}
}
}
}
}
void* map_in_file(const utility::umt_optstruct_t* testops, uint64_t numbytes)
{
void* region = NULL;
int open_options = O_RDWR | O_LARGEFILE | O_DIRECT;
int fd;
string filename(testops->filename);
if ( testops->initonly || !testops->noinit ) {
open_options |= O_CREAT;
unlink(filename.c_str()); // Remove the file if it exists
}
if ( ( fd = open(filename.c_str(), open_options, S_IRUSR | S_IWUSR) ) == -1 ) {
string estr = "Failed to open/create " + filename + ": ";
perror(estr.c_str());
return NULL;
}
if ( open_options & O_CREAT ) { // If we are initializing, attempt to pre-allocate disk space for the file.
try {
int x;
if ( ( x = posix_fallocate(fd, 0, numbytes) != 0 ) ) {
ostringstream ss;
ss << "Failed to pre-allocate " << numbytes << " bytes in " << filename << ": ";
perror(ss.str().c_str());
return NULL;
}
} catch(const std::exception& e) {
cerr << "posix_fallocate: " << e.what() << endl;
return NULL;
} catch(...) {
cerr << "posix_fallocate failed to allocate backing store\n";
return NULL;
}
}
struct stat sbuf;
if (fstat(fd, &sbuf) == -1) {
string estr = "Failed to get status (fstat) for " + filename + ": ";
perror(estr.c_str());
return NULL;
}
if ( (off_t)sbuf.st_size != (numbytes) ) {
cerr << filename << " size " << sbuf.st_size << " does not match specified data size of " << (numbytes) << endl;
return NULL;
}
const int prot = PROT_READ|PROT_WRITE;
if ( testops->usemmap ) {
region = mmap(NULL, numbytes, prot, MAP_SHARED | MAP_NORESERVE, fd, 0);
if (region == MAP_FAILED) {
ostringstream ss;
ss << "mmap of " << numbytes << " bytes failed for " << filename << ": ";
perror(ss.str().c_str());
return NULL;
}
}
else {
int flags = UMAP_PRIVATE;
region = umap(NULL, numbytes, prot, flags, fd, 0);
if ( region == UMAP_FAILED ) {
ostringstream ss;
ss << "umap_mf of " << numbytes << " bytes failed for " << filename << ": ";
perror(ss.str().c_str());
return NULL;
}
}
return region;
}
void unmap_file(const utility::umt_optstruct_t* testops, uint64_t numbytes, void* region)
{
if ( testops->usemmap ) {
if ( munmap(region, numbytes) < 0 ) {
ostringstream ss;
ss << "munmap failure: ";
perror(ss.str().c_str());
exit(-1);
}
}
else {
if (uunmap(region, numbytes) < 0) {
ostringstream ss;
ss << "uunmap of failure: ";
perror(ss.str().c_str());
exit(-1);
}
}
}
int main(int argc, char **argv)
{
utility::umt_optstruct_t options;
uint64_t pagesize;
uint64_t totalbytes;
uint64_t arraysize;
void* base_addr;
uint64_t start = getns();
pagesize = (uint64_t)utility::umt_getpagesize();
umt_getoptions(&options, argc, argv);
omp_set_num_threads(options.numthreads);
totalbytes = options.numpages*pagesize;
base_addr = utility::map_in_file(options.filename, options.initonly, options.noinit, options.usemmap, totalbytes);
if (base_addr == nullptr)
return -1;
fprintf(stdout, "umap INIT took %f seconds\n", (double)(getns() - start)/1000000000.0);
fprintf(stdout, "%lu pages, %llu bytes, %lu threads\n", options.numpages, totalbytes, options.numthreads);
uint64_t *arr = (uint64_t *) base_addr;
arraysize = totalbytes/sizeof(uint64_t);
start = getns();
if ( !options.noinit ) {
// init data
initdata(arr, arraysize);
fprintf(stdout, "Init took %f seconds\n", (double)(getns() - start)/1000000000.0);
}
if ( !options.initonly )
{
start = getns();
sort_ascending = (arr[0] != 1);
if (sort_ascending == true) {
printf("Sorting in Ascending Order\n");
__gnu_parallel::sort(arr, &arr[arraysize], std::less<uint64_t>(), __gnu_parallel::quicksort_tag());
}
else {
printf("Sorting in Descending Order\n");
__gnu_parallel::sort(arr, &arr[arraysize], std::greater<uint64_t>(), __gnu_parallel::quicksort_tag());
}
fprintf(stdout, "Sort took %f seconds\n", (double)(getns() - start)/1000000000.0);
start = getns();
validatedata(arr, arraysize);
fprintf(stdout, "Validate took %f seconds\n", (double)(getns() - start)/1000000000.0);
}
start = getns();
utility::unmap_file(options.usemmap, totalbytes, base_addr);
fprintf(stdout, "umap TERM took %f seconds\n", (double)(getns() - start)/1000000000.0);
return 0;
}
Includes¶
../utility/commandline.hpp
../utility/umap_file.hpp
cassert
fcntl.h
iostream
omp.h
parallel/algorithm
random
(File run_random_vector.cpp)sstream
string
sys/stat.h
sys/types.h
umap/umap.h
vector
(File run_random_vector.cpp)
Functions¶
Defines¶
Variables¶
File utility.hpp¶
↰ Parent directory (median_calculation
)
Contents
Definition (median_calculation/utility.hpp
)¶
↰ Return to documentation for file (median_calculation/utility.hpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/// Memo about median calculation
/// x: horizontal dimension of a frame at a certain time point
/// y: vertical dimension of a frame at a certain time point
/// k: time dimension
/// A cube is a set of 'k' frames
#ifndef MEDIAN_CALCULATION_COMMON_HPP
#define MEDIAN_CALCULATION_COMMON_HPP
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <cfenv>
#include <cassert>
#define MEDIAN_CALCULATION_COLUMN_MAJOR 1
// #define MEDIAN_CALCULATION_VERBOSE_OUT_OF_RANGE
namespace median
{
template <typename _pixel_type>
struct cube_t {
using pixel_type = _pixel_type;
size_t size_x;
size_t size_y;
size_t size_k;
pixel_type *data;
};
/// \brief Return frame size
template <typename pixel_type>
inline size_t get_frame_size(const cube_t<pixel_type>& cube)
{
return cube.size_x * cube.size_y;
}
/// \brief Return cube size
template <typename pixel_type>
inline size_t get_cube_size(const cube_t<pixel_type>& cube)
{
return cube.size_x * cube.size_y * cube.size_k;
}
/// \brief Returns an index of a 3D coordinate
template <typename pixel_type>
inline ssize_t get_index(const cube_t<pixel_type>& cube, const size_t x, const size_t y, const size_t k)
{
#if MEDIAN_CALCULATION_COLUMN_MAJOR
const ssize_t frame_index = x + y * cube.size_x;
#else
const ssize_t frame_index = x * cube.size_y + y;
#endif
if (get_frame_size(cube) <= frame_index) {
#ifdef MEDIAN_CALCULATION_VERBOSE_OUT_OF_RANGE
std::cerr << "Frame index is out-of-range: "
<< "(" << x << ", " << y << ") is out of "
<< "(" << cube.size_x << ", " << cube.size_y << ")" << std::endl;
#endif
return -1;
}
const ssize_t cube_index = frame_index + k * get_frame_size(cube);
if (get_cube_size(cube) <= cube_index) {
#ifdef MEDIAN_CALCULATION_VERBOSE_OUT_OF_RANGE
std::cerr << "Cube index is out-of-range: "
<< "(" << x << ", " << y << ", " << k << ") is out of "
<< "(" << cube.size_x << ", " << cube.size_y << ", " << cube.size_k << ")" << std::endl;
#endif
return -1;
}
return cube_index;
}
/// \brief Reverses byte order
/// \tparam T Type of value; currently only 4 Byte types are supported
/// \param x Input value
/// \return Given value being reversed byte order
template <typename T>
inline T reverse_byte_order(const T x)
{
static_assert(sizeof(T) == 4, "T is not a 4 byte of type");
T reversed_x;
auto *const p1 = reinterpret_cast<const char *>(&x);
auto *const p2 = reinterpret_cast<char *>(&reversed_x);
p2[0] = p1[3];
p2[1] = p1[2];
p2[2] = p1[1];
p2[3] = p1[0];
return reversed_x;
}
template <typename pixel_type>
bool is_nan(const pixel_type value)
{
return std::isnan(value);
}
} // namespace median
#endif //MEDIAN_CALCULATION_COMMON_HPP
Includes¶
cassert
cfenv
cmath
fstream
iomanip
iostream
string
Namespaces¶
Classes¶
Functions¶
File vector.hpp¶
↰ Parent directory (median_calculation
)
Definition (median_calculation/vector.hpp
)¶
↰ Return to documentation for file (median_calculation/vector.hpp
)
/*
This file is part of UMAP. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/umap/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UMAP_VECTOR_HPP
#define UMAP_VECTOR_HPP
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>
#include <cassert>
#include "utility.hpp"
struct vector_t
{
double x_intercept;
double x_slope;
double y_intercept;
double y_slope;
};
/// \brief Returns an index of a 3D coordinate. vector version
template <typename pixel_type>
inline ssize_t get_index(const median::cube_t<pixel_type>& cube, const vector_t& vec, const size_t epoch)
{
return median::get_index(cube,
std::round(vec.x_slope * epoch + vec.x_intercept),
std::round(vec.y_slope * epoch + vec.y_intercept),
epoch);
}
// Iterator class to use torben function with vector model
// This class is a minimum implementation of an iterator to use the torben function
template <typename pixel_type>
class vector_iterator {
public:
// Required types to use some stl functions
using value_type = pixel_type;
using difference_type = ssize_t;
using iterator_category = std::random_access_iterator_tag;
using pointer = value_type *;
using reference = value_type &;
// Constructor
vector_iterator(const median::cube_t<pixel_type> &_cube,
const vector_t &_vector,
const size_t _start_pos)
: cube(_cube),
vector(_vector),
current_pos(_start_pos) {
// Note that when 'end' iterator is given to copy-constructor and MEDIAN_CALCULATION_VERBOSE_OUT_OF_RANGE is ON,
// this code will trigger the out-of-range error message in get_index() function
// although passing an 'end' iterator to copy-constructor is an expected behaivor
if (is_out_of_range(current_pos)) {
move_to_end();
return;
}
const value_type current_value = *(*this);
if (median::is_nan(current_value)) {
move_to_next_valid_position();
}
}
// Use default copy constructor
vector_iterator(const vector_iterator&) = default;
// To support
// iterator1 == iterator2
bool operator==(const vector_iterator &other) {
return current_pos == other.current_pos;
}
// To support
// iterator1 != iterator2
bool operator!=(const vector_iterator &other) {
return !(*this == other);
}
// To support
// difference_type diff = iterator2 - iterator1
difference_type operator-(const vector_iterator &other) {
return current_pos - other.current_pos;
}
// To support
// value_type val = *iterator
value_type operator*() {
assert(!is_out_of_range(current_pos)); // for sanitary check
return median::reverse_byte_order(cube.data[get_index(cube, vector, current_pos)]);
}
// To support
// ++iterator
vector_iterator& operator++() {
move_to_next_valid_position();
return (*this);
}
// Utility function returns an iterator object pointing the end
static vector_iterator create_end(const median::cube_t<pixel_type> &cube, const vector_t &vector) {
vector_iterator iterator(cube, vector, 0); // 0 is a dummy value
iterator.move_to_end();
return iterator;
}
private:
void move_to_next_valid_position() {
++current_pos;
// Skip 'nan' values
// When the vector is outside of the cube, move to the 'end' position
while (true) {
if (cube.size_k <= current_pos) {
move_to_end();
break;
}
if (is_out_of_range(current_pos)) {
move_to_end();
break;
}
const value_type current_value = *(*this);
if (!median::is_nan(current_value)) {
break; // Found next non-'nan' value
}
++current_pos;
}
}
// move position to the 'end' position
void move_to_end() {
current_pos = cube.size_k;
}
bool is_out_of_range(const size_t pos) {
return (get_index(cube, vector, pos) == -1);
}
median::cube_t<pixel_type> cube;
vector_t vector;
size_t current_pos;
};
#endif //UMAP_VECTOR_HPP
Includes¶
algorithm
cassert
iostream
random
(File run_random_vector.cpp)utility.hpp
(File utility.hpp)vector
(File run_random_vector.cpp)