diff options
author | Håvard Pettersen <havardpe@oath.com> | 2020-06-17 15:15:30 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2020-06-18 10:21:48 +0000 |
commit | 9b475a9b958ccf56a8c793021d21cdde09d39e15 (patch) | |
tree | d6e04e4ad2d8ed8d284447673e911fd9a7df24a8 /eval | |
parent | d3b332d3d9772b4cdff30ad68c87d5a525c119eb (diff) |
observe the results of multiply-add across implementations
- add specific test showing diverging results when using FMA
- re-write eval test to not fail due to FMA
- re-write hitcollector test to not fail due to FMA
Diffstat (limited to 'eval')
-rw-r--r-- | eval/CMakeLists.txt | 1 | ||||
-rw-r--r-- | eval/src/tests/eval/multiply_add/CMakeLists.txt | 9 | ||||
-rw-r--r-- | eval/src/tests/eval/multiply_add/multiply_add_test.cpp | 44 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/test/eval_spec.cpp | 6 |
4 files changed, 57 insertions, 3 deletions
diff --git a/eval/CMakeLists.txt b/eval/CMakeLists.txt index 3a9aabc83ba..3e81521550a 100644 --- a/eval/CMakeLists.txt +++ b/eval/CMakeLists.txt @@ -19,6 +19,7 @@ vespa_define_module( src/tests/eval/gbdt src/tests/eval/inline_operation src/tests/eval/interpreted_function + src/tests/eval/multiply_add src/tests/eval/node_tools src/tests/eval/node_types src/tests/eval/param_usage diff --git a/eval/src/tests/eval/multiply_add/CMakeLists.txt b/eval/src/tests/eval/multiply_add/CMakeLists.txt new file mode 100644 index 00000000000..c50aa4f50a2 --- /dev/null +++ b/eval/src/tests/eval/multiply_add/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(eval_multiply_add_test_app TEST + SOURCES + multiply_add_test.cpp + DEPENDS + vespaeval + gtest +) +vespa_add_test(NAME eval_multiply_add_test_app COMMAND eval_multiply_add_test_app) diff --git a/eval/src/tests/eval/multiply_add/multiply_add_test.cpp b/eval/src/tests/eval/multiply_add/multiply_add_test.cpp new file mode 100644 index 00000000000..35cab0a6030 --- /dev/null +++ b/eval/src/tests/eval/multiply_add/multiply_add_test.cpp @@ -0,0 +1,44 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/eval/eval/function.h> +#include <vespa/eval/eval/llvm/compiled_function.h> +#include <vespa/eval/eval/interpreted_function.h> +#include <vespa/eval/tensor/default_tensor_engine.h> +#include <vespa/vespalib/gtest/gtest.h> + +using namespace vespalib::eval; + +using Engine = vespalib::tensor::DefaultTensorEngine; + +double gcc_fun(double a, double b) { + return (a * 3) + b; +} + +TEST(MultiplyAddTest, multiply_add_gives_same_result) { + auto fun = Function::parse("a*3+b"); + CompiledFunction cfun(*fun, PassParams::ARRAY); + NodeTypes node_types = NodeTypes(*fun, {ValueType::double_type(), ValueType::double_type()}); + InterpretedFunction ifun(Engine::ref(), *fun, node_types); + auto llvm_fun = cfun.get_function(); + //------------------------------------------------------------------------- + double a = -1.0/3.0; + double b = 1.0; + std::vector<double> ab({a, b}); + SimpleParams params(ab); + InterpretedFunction::Context ictx(ifun); + //------------------------------------------------------------------------- + const Value &result_value = ifun.eval(ictx, params); + double ifun_res = result_value.as_double(); + double llvm_res = llvm_fun(&ab[0]); + double gcc_res = gcc_fun(a, b); + fprintf(stderr, "ifun_res: %a\n", ifun_res); + fprintf(stderr, "llvm_res: %a\n", llvm_res); + fprintf(stderr, "gcc_res: %a\n", gcc_res); + EXPECT_EQ(ifun_res, llvm_res); + EXPECT_DOUBLE_EQ(llvm_res + 1.0, gcc_res + 1.0); + if (llvm_res != gcc_res) { + fprintf(stderr, "WARNING: diverging results caused by fused multiply add\n"); + } +} + +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/vespa/eval/eval/test/eval_spec.cpp b/eval/src/vespa/eval/eval/test/eval_spec.cpp index 709234a1a2c..dbc20dcf606 100644 --- a/eval/src/vespa/eval/eval/test/eval_spec.cpp +++ b/eval/src/vespa/eval/eval/test/eval_spec.cpp @@ -162,11 +162,11 @@ EvalSpec::add_function_call_cases() { void EvalSpec::add_tensor_operation_cases() { add_rule({"a", -1.0, 1.0}, "map(a,f(x)(sin(x)))", [](double x){ return std::sin(x); }); - add_rule({"a", -1.0, 1.0}, "map(a,f(x)(x+x*3))", [](double x){ return (x + (x * 3)); }); + add_rule({"a", -1.0, 1.0}, "map(a,f(x)(x*x*3))", [](double x){ return ((x * x) * 3); }); add_rule({"a", -1.0, 1.0}, {"b", -1.0, 1.0}, "join(a,b,f(x,y)(x+y))", [](double x, double y){ return (x + y); }); - add_rule({"a", -1.0, 1.0}, {"b", -1.0, 1.0}, "join(a,b,f(x,y)(x+y*3))", [](double x, double y){ return (x + (y * 3)); }); + add_rule({"a", -1.0, 1.0}, {"b", -1.0, 1.0}, "join(a,b,f(x,y)(x*y*3))", [](double x, double y){ return ((x * y) * 3); }); add_rule({"a", -1.0, 1.0}, {"b", -1.0, 1.0}, "merge(a,b,f(x,y)(x+y))", [](double x, double y){ return (x + y); }); - add_rule({"a", -1.0, 1.0}, {"b", -1.0, 1.0}, "merge(a,b,f(x,y)(x+y*3))", [](double x, double y){ return (x + (y * 3)); }); + add_rule({"a", -1.0, 1.0}, {"b", -1.0, 1.0}, "merge(a,b,f(x,y)(x*y*3))", [](double x, double y){ return ((x * y) * 3); }); add_rule({"a", -1.0, 1.0}, "reduce(a,avg)", [](double a){ return a; }); add_rule({"a", -1.0, 1.0}, "reduce(a,count)", [](double){ return 1.0; }); add_rule({"a", -1.0, 1.0}, "reduce(a,prod)", [](double a){ return a; }); |