Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add binary IO for matrix_data #984

Merged
merged 3 commits into from
Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benchmark/conversions/conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ int main(int argc, char* argv[])
std::ifstream mtx_fd(test_case["filename"].GetString());
gko::matrix_data<etype, itype> data;
try {
data = gko::read_raw<etype, itype>(mtx_fd);
data = gko::read_generic_raw<etype, itype>(mtx_fd);
} catch (std::exception& e) {
std::cerr << "Error setting up matrix data, what(): " << e.what()
<< std::endl;
Expand Down
2 changes: 1 addition & 1 deletion benchmark/matrix_statistics/matrix_statistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ int main(int argc, char* argv[])
std::clog << "Running test case: " << test_case << std::endl;

std::ifstream ifs(test_case["filename"].GetString());
auto matrix = gko::read_raw<etype, gko::int64>(ifs);
auto matrix = gko::read_generic_raw<etype, gko::int64>(ifs);
ifs.close();

std::clog << "Matrix is of size (" << matrix.size[0] << ", "
Expand Down
2 changes: 1 addition & 1 deletion benchmark/preconditioner/preconditioner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ int main(int argc, char* argv[])
std::clog << "Running test case: " << test_case << std::endl;

std::ifstream mtx_fd(test_case["filename"].GetString());
auto data = gko::read_raw<etype, itype>(mtx_fd);
auto data = gko::read_generic_raw<etype, itype>(mtx_fd);

auto system_matrix =
share(formats::matrix_factory.at(FLAGS_formats)(exec, data));
Expand Down
2 changes: 1 addition & 1 deletion benchmark/solver/solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ int main(int argc, char* argv[])
{std::numeric_limits<rc_etype>::quiet_NaN()}, exec);
x = gko::initialize<Vec>({0.0}, exec);
} else {
auto data = gko::read_raw<etype, itype>(mtx_fd);
auto data = gko::read_generic_raw<etype, itype>(mtx_fd);
system_matrix = share(formats::matrix_factory.at(
test_case["optimal"]["spmv"].GetString())(exec, data));
if (test_case.HasMember("rhs")) {
Expand Down
2 changes: 1 addition & 1 deletion benchmark/sparse_blas/sparse_blas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ int main(int argc, char* argv[])
auto& sp_blas_case = test_case[benchmark_name];
std::clog << "Running test case: " << test_case << std::endl;
std::ifstream mtx_fd(test_case["filename"].GetString());
auto data = gko::read_raw<etype, itype>(mtx_fd);
auto data = gko::read_generic_raw<etype, itype>(mtx_fd);
data.ensure_row_major_order();
std::clog << "Matrix is of size (" << data.size[0] << ", "
<< data.size[1] << "), " << data.nonzeros.size()
Expand Down
2 changes: 1 addition & 1 deletion benchmark/spmv/spmv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ int main(int argc, char* argv[])
}
std::clog << "Running test case: " << test_case << std::endl;
std::ifstream mtx_fd(test_case["filename"].GetString());
auto data = gko::read_raw<etype, itype>(mtx_fd);
auto data = gko::read_generic_raw<etype, itype>(mtx_fd);

auto nrhs = FLAGS_nrhs;
auto b = create_matrix<etype>(exec, gko::dim<2>{data.size[1], nrhs},
Expand Down
4 changes: 3 additions & 1 deletion benchmark/tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ add_executable(matrix matrix.cpp)
add_executable(matrix_complex matrix.cpp)
target_compile_definitions(matrix_complex PRIVATE GKO_TOOL_COMPLEX)
target_link_libraries(matrix Ginkgo::ginkgo)
target_link_libraries(matrix_complex Ginkgo::ginkgo)
target_link_libraries(matrix_complex Ginkgo::ginkgo)
add_executable(mtx_to_binary mtx_to_binary.cpp)
target_link_libraries(mtx_to_binary Ginkgo::ginkgo)
16 changes: 11 additions & 5 deletions benchmark/tools/matrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,10 @@ int main(int argc, char** argv)
if (argc == 1) {
std::cerr
<< "Usage: " << argv[0]
<< " [operation1] [operation2]\nApplies the given operations "
<< " [-b] [operation1] [operation2]\nApplies the given operations "
"to the input matrix read from stdin\nand writes it to "
"stdout.\nOperations are:\n"
"stdout.\nUses binary format if -b is set, otherwise matrix "
"market format.Operations are:\n"
" lower-triangular removes nonzeros above the diagonal\n"
" upper-triangular removes nonzeros below the diagonal\n"
" remove-diagonal removes diagonal entries\n"
Expand All @@ -194,10 +195,11 @@ int main(int argc, char** argv)
<< std::endl;
return 1;
}
bool binary = std::string{argv[1]} == "-b";

auto data = gko::read_raw<value_type, gko::int64>(std::cin);
auto data = gko::read_generic_raw<value_type, gko::int64>(std::cin);
data.ensure_row_major_order();
for (int argi = 1; argi < argc; argi++) {
for (int argi = binary ? 2 : 1; argi < argc; argi++) {
std::string arg{argv[argi]};
if (arg == "lower-triangular") {
data = make_lower_triangular(data);
Expand Down Expand Up @@ -232,5 +234,9 @@ int main(int argc, char** argv)
return 1;
}
}
gko::write_raw(std::cout, data, gko::layout_type::coordinate);
if (binary) {
gko::write_binary_raw(std::cout, data);
} else {
gko::write_raw(std::cout, data, gko::layout_type::coordinate);
}
}
114 changes: 114 additions & 0 deletions benchmark/tools/mtx_to_binary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*******************************<GINKGO LICENSE>******************************
Copyright (c) 2017-2022, the Ginkgo authors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************<GINKGO LICENSE>*******************************/

#include <fstream>
#include <ios>
#include <limits>


#include <ginkgo/core/base/exception_helpers.hpp>
#include <ginkgo/core/base/mtx_io.hpp>


template <typename ValueType>
void process(const char* input, const char* output, bool validate)
{
std::ifstream is(input);
std::cerr << "Reading from " << input << '\n';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using clog?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think providing immediate output is more useful here for long-running conversions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or using std::endl will flush it
Is any reason to use cerr not cout here? for me, these are information not error message

Copy link
Member Author

@upsj upsj Mar 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, cout is for output that can be passed on to other tools e.g. via pipes/redirects, cerr is for status and error messages. As there is no useful information to be passed on, I don't use cout

auto data = gko::read_raw<ValueType, gko::int64>(is);
{
std::ofstream os(output, std::ios_base::out | std::ios_base::binary);
std::cerr << "Writing to " << output << '\n';
if (data.size[0] <= std::numeric_limits<gko::int32>::max()) {
gko::matrix_data<ValueType, gko::int32> int_data(data.size);
for (auto entry : data.nonzeros) {
int_data.nonzeros.emplace_back(
static_cast<gko::int32>(entry.row),
static_cast<gko::int32>(entry.column), entry.value);
}
gko::write_binary_raw(os, int_data);
} else {
gko::write_binary_raw(os, data);
}
}
if (validate) {
std::ifstream ois(output, std::ios_base::in | std::ios_base::binary);
auto data2 = gko::read_binary_raw<ValueType, gko::int64>(ois);
std::cerr << "Comparing against previously read data\n";
if (data.size != data2.size) {
throw GKO_STREAM_ERROR("Mismatching sizes!");
}
if (data.nonzeros != data2.nonzeros) {
throw GKO_STREAM_ERROR("Differing data!");
}
std::cerr << "Validation successful!\n";
}
}


int main(int argc, char** argv)
{
if (argc < 3 || (std::string{argv[1]} == "-v" && argc < 4)) {
std::cerr
<< "Usage: " << argv[0]
<< " [-v] [input] [output]\n"
"Reads the input file in MatrixMarket format and converts it"
"to Ginkgo's binary format.\nWith the optional -v flag, reads "
"the written binary output again and compares it with the "
"original input to validate the conversion.\n"
"The conversion uses a complex value type if necessary, "
"the highest possible value precision and the smallest "
"possible index type.\n";
return 1;
}
bool validate = std::string{argv[1]} == "-v";
const auto input = validate ? argv[2] : argv[1];
const auto output = validate ? argv[3] : argv[2];
std::string header;
{
// read header, close file again
std::ifstream is(input);
std::getline(is, header);
}
try {
if (header.find("complex") != std::string::npos) {
std::cerr << "Input matrix is complex\n";
process<std::complex<double>>(input, output, validate);
} else {
std::cerr << "Input matrix is real\n";
process<double>(input, output, validate);
}
} catch (gko::Error& err) {
std::cerr << err.what() << '\n';
return 2;
}
}
Loading