|
| 1 | +/* |
| 2 | + * Copyright 2021 Huawei Technologies Co., Ltd. |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | + |
| 17 | +#include <exception> |
| 18 | +#include <iostream> |
| 19 | +#include <vector> |
| 20 | + |
| 21 | +#include <inttypes.h> |
| 22 | + |
| 23 | +#include <graphblas/algorithms/sssp.hpp> |
| 24 | +#include <graphblas/utils/Timer.hpp> |
| 25 | +#include <graphblas/utils/parser.hpp> |
| 26 | + |
| 27 | +#include <graphblas.hpp> |
| 28 | +#include <utils/output_verification.hpp> |
| 29 | + |
| 30 | +template< typename T > |
| 31 | +grb::Vector< T > stdToGrbVector( const std::vector< T > & in ) { |
| 32 | + grb::Vector< T > out( in.size() ); |
| 33 | + for( size_t i = 0; i < in.size(); i++ ) |
| 34 | + grb::setElement( out, in[ i ], i ); |
| 35 | + return out; |
| 36 | +} |
| 37 | + |
| 38 | +template< typename T > |
| 39 | +struct input_t { |
| 40 | + grb::Matrix< T > A; |
| 41 | + size_t root; |
| 42 | + const grb::Vector< T > & expected_distances; |
| 43 | +}; |
| 44 | + |
| 45 | +struct output_t { |
| 46 | + grb::RC rc = grb::RC::SUCCESS; |
| 47 | + grb::utils::TimerResults times; |
| 48 | + size_t data_in_local; |
| 49 | +}; |
| 50 | + |
| 51 | +template< typename T > |
| 52 | +void grbProgram( const struct input_t< T > & input, struct output_t & output ) { |
| 53 | + std::cout << std::endl << "Running SSSP" << std::endl; |
| 54 | + grb::utils::Timer timer; |
| 55 | + |
| 56 | + grb::Vector< T > distances( grb::nrows( input.A ) ); |
| 57 | + |
| 58 | + timer.reset(); |
| 59 | + output.rc = output.rc ? output.rc : grb::algorithms::sssp( input.A, input.root, distances ); |
| 60 | + timer.reset(); |
| 61 | + |
| 62 | + // Check distances by comparing it with the expected one |
| 63 | + if( std::equal( input.expected_distances.cbegin(), input.expected_distances.cend(), distances.cbegin() ) ) { |
| 64 | + std::cout << "SUCCESS: distances are correct" << std::endl; |
| 65 | + } else { |
| 66 | + std::cerr << "FAILED: distances are incorrect" << std::endl; |
| 67 | + std::cerr << "distances != expected_distances" << std::endl; |
| 68 | + for( size_t i = 0; i < grb::nrows( input.A ); i++ ) |
| 69 | + std::cerr << std::string( 3, ' ' ) << distances[ i ] << " | " << input.expected_distances[ i ] << std::endl; |
| 70 | + output.rc = grb::RC::FAILED; |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +int main( int argc, char ** argv ) { |
| 75 | + (void)argc; |
| 76 | + (void)argv; |
| 77 | + constexpr size_t niterations = 1; |
| 78 | + |
| 79 | + grb::Benchmarker< grb::EXEC_MODE::AUTOMATIC > benchmarker; |
| 80 | + std::cout << "Test executable: " << argv[ 0 ] << std::endl; |
| 81 | + |
| 82 | + // Check if we are testing on a file |
| 83 | + if( argc != 1 && argc != 4 ) { |
| 84 | + std::cerr << "Usage: \n\t" << argv[ 0 ] << " [ <graph_filepath> <root> <expected_distances_filepath> ]" << std::endl; |
| 85 | + return 1; |
| 86 | + } |
| 87 | + bool test_on_file = ( argc == 4 ); |
| 88 | + |
| 89 | + if( test_on_file ) { // Test on a file |
| 90 | + std::string graph_filepath( argv[ 1 ] ); |
| 91 | + size_t root = std::stoul( argv[ 2 ] ); |
| 92 | + std::string expected_distances_filepath( argv[ 3 ] ); |
| 93 | + |
| 94 | + std::cout << "-- Running test on file " << graph_filepath << std::endl; |
| 95 | + |
| 96 | + // Read matrix from file |
| 97 | + grb::utils::MatrixFileReader< double > reader( graph_filepath, false, true ); |
| 98 | + size_t r = reader.n(), c = reader.m(); |
| 99 | + assert( r == c ); |
| 100 | + grb::Matrix< double > A( r, c ); |
| 101 | + grb::RC rc_build = buildMatrixUnique( A, reader.cbegin( grb::IOMode::SEQUENTIAL ), reader.cend( grb::IOMode::SEQUENTIAL ), grb::IOMode::PARALLEL ); |
| 102 | + if( rc_build != grb::RC::SUCCESS ) { |
| 103 | + std::cerr << "ERROR during buildMatrixUnique: rc = " << rc_build << std::endl; |
| 104 | + return 1; |
| 105 | + } |
| 106 | + std::cout << "Matrix read successfully" << std::endl; |
| 107 | + grb::Vector< double > expected_distances( r ); |
| 108 | + // TODO: Read expected_distances vector from file |
| 109 | + // Run the algorithm |
| 110 | + input_t< double > input { A, root, expected_distances }; |
| 111 | + output_t output; |
| 112 | + grb::RC bench_rc = benchmarker.exec( &grbProgram, input, output, niterations, 1, true ); |
| 113 | + if( bench_rc ) { |
| 114 | + std::cerr << "ERROR during execution on file " << graph_filepath << ": rc = " << bench_rc << std::endl; |
| 115 | + return bench_rc; |
| 116 | + } else if( output.rc ) { |
| 117 | + std::cerr << "Test failed: rc = " << output.rc << std::endl; |
| 118 | + return output.rc; |
| 119 | + } |
| 120 | + } else { |
| 121 | + |
| 122 | + /** Matrix A1: |
| 123 | + * |
| 124 | + * Schema: |
| 125 | + * 0 ----- 1 |
| 126 | + * | \ |
| 127 | + * | \ |
| 128 | + * | \ |
| 129 | + * 2 3 |
| 130 | + * |
| 131 | + */ |
| 132 | + { // Directed version, root = 0, uniform weights = 1 |
| 133 | + size_t root = 0; |
| 134 | + std::vector< double > expected_distances { 0, 1, 1, 1 }; |
| 135 | + std::cout << "-- Running test on A1 (directed, root " + std::to_string( root ) + ")" << std::endl; |
| 136 | + grb::Matrix< double > A( 4, 4 ); |
| 137 | + std::vector< size_t > A_rows { { 0, 0, 0 } }; |
| 138 | + std::vector< size_t > A_cols { { 1, 2, 3 } }; |
| 139 | + std::vector< double > A_values( A_rows.size(), 1 ); |
| 140 | + grb::buildMatrixUnique( A, A_rows.data(), A_cols.data(), A_values.data(), A_rows.size(), grb::IOMode::PARALLEL ); |
| 141 | + input_t< double > input { A, root, stdToGrbVector( expected_distances ) }; |
| 142 | + output_t output; |
| 143 | + grb::RC bench_rc = benchmarker.exec( &grbProgram, input, output, niterations, 1, true ); |
| 144 | + if( bench_rc ) { |
| 145 | + std::cerr << "ERROR during execution: rc = " << bench_rc << std::endl; |
| 146 | + return bench_rc; |
| 147 | + } else if( output.rc ) { |
| 148 | + std::cerr << "Test failed: rc = " << output.rc << std::endl; |
| 149 | + return output.rc; |
| 150 | + } |
| 151 | + std::cout << std::endl; |
| 152 | + } |
| 153 | + |
| 154 | + /** Matrix A2: |
| 155 | + * |
| 156 | + * Schema: |
| 157 | + * 0 ----- 2 ----- 3 |
| 158 | + * | |
| 159 | + * | |
| 160 | + * | |
| 161 | + * 1 |
| 162 | + * |
| 163 | + */ |
| 164 | + { // Directed version, root = 0, uniform weights = 1 |
| 165 | + size_t root = 0; |
| 166 | + std::vector< double > expected_distances { 0, 1, 1, 2 }; |
| 167 | + std::cout << "-- Running test on A2 (directed, root " + std::to_string( root ) + ")" << std::endl; |
| 168 | + grb::Matrix< double > A( 4, 4 ); |
| 169 | + std::vector< size_t > A_rows { { 0, 0, 2 } }; |
| 170 | + std::vector< size_t > A_cols { { 1, 2, 3 } }; |
| 171 | + std::vector< double > A_values( A_rows.size(), 1 ); |
| 172 | + grb::buildMatrixUnique( A, A_rows.data(), A_cols.data(), A_values.data(), A_rows.size(), grb::IOMode::PARALLEL ); |
| 173 | + input_t< double > input { A, root, stdToGrbVector( expected_distances ) }; |
| 174 | + output_t output; |
| 175 | + grb::RC bench_rc = benchmarker.exec( &grbProgram, input, output, niterations, 1, true ); |
| 176 | + if( bench_rc ) { |
| 177 | + std::cerr << "ERROR during execution: rc = " << bench_rc << std::endl; |
| 178 | + return bench_rc; |
| 179 | + } else if( output.rc ) { |
| 180 | + std::cerr << "Test failed: rc = " << output.rc << std::endl; |
| 181 | + return output.rc; |
| 182 | + } |
| 183 | + std::cout << std::endl; |
| 184 | + } |
| 185 | + |
| 186 | + /** Matrix A3: |
| 187 | + * |
| 188 | + * Schema: |
| 189 | + * |
| 190 | + * 0 ----- 1 ----- 2 ----- 3 |
| 191 | + * |
| 192 | + */ |
| 193 | + { // Directed version, root = 0, uniform weights = 1 |
| 194 | + size_t root = 0; |
| 195 | + std::vector< double > expected_distances { 0, 1, 2, 3 }; |
| 196 | + std::cout << "-- Running test on A2.1 (directed, root " + std::to_string( root ) + ")" << std::endl; |
| 197 | + grb::Matrix< double > A( 4, 4 ); |
| 198 | + std::vector< size_t > A_rows { { 0, 0, 2 } }; |
| 199 | + std::vector< size_t > A_cols { { 1, 2, 3 } }; |
| 200 | + std::vector< double > A_values( A_rows.size(), 1 ); |
| 201 | + grb::buildMatrixUnique( A, A_rows.data(), A_cols.data(), A_values.data(), A_rows.size(), grb::IOMode::PARALLEL ); |
| 202 | + input_t< double > input { A, root, stdToGrbVector( expected_distances ) }; |
| 203 | + output_t output; |
| 204 | + grb::RC bench_rc = benchmarker.exec( &grbProgram, input, output, niterations, 1, true ); |
| 205 | + if( bench_rc ) { |
| 206 | + std::cerr << "ERROR during execution: rc = " << bench_rc << std::endl; |
| 207 | + return bench_rc; |
| 208 | + } else if( output.rc ) { |
| 209 | + std::cerr << "Test failed: rc = " << output.rc << std::endl; |
| 210 | + return output.rc; |
| 211 | + } |
| 212 | + std::cout << std::endl; |
| 213 | + } |
| 214 | + { // Directed version, root = 0, uniform weights = 10 |
| 215 | + size_t root = 0; |
| 216 | + std::vector< double > expected_distances { 0, 10, 10, 30 }; |
| 217 | + std::cout << "-- Running test on A2.2 (directed, root " + std::to_string( root ) + ")" << std::endl; |
| 218 | + grb::Matrix< double > A( 4, 4 ); |
| 219 | + std::vector< size_t > A_rows { { 0, 0, 2 } }; |
| 220 | + std::vector< size_t > A_cols { { 1, 2, 3 } }; |
| 221 | + std::vector< double > A_values( A_rows.size(), 10 ); |
| 222 | + grb::buildMatrixUnique( A, A_rows.data(), A_cols.data(), A_values.data(), A_rows.size(), grb::IOMode::PARALLEL ); |
| 223 | + input_t< double > input { A, root, stdToGrbVector( expected_distances ) }; |
| 224 | + output_t output; |
| 225 | + grb::RC bench_rc = benchmarker.exec( &grbProgram, input, output, niterations, 1, true ); |
| 226 | + if( bench_rc ) { |
| 227 | + std::cerr << "ERROR during execution: rc = " << bench_rc << std::endl; |
| 228 | + return bench_rc; |
| 229 | + } else if( output.rc ) { |
| 230 | + std::cerr << "Test failed: rc = " << output.rc << std::endl; |
| 231 | + return output.rc; |
| 232 | + } |
| 233 | + std::cout << std::endl; |
| 234 | + } |
| 235 | + } |
| 236 | + std::cout << "Test OK" << std::endl; |
| 237 | + |
| 238 | + return 0; |
| 239 | +} |
0 commit comments