summaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2020-06-17 15:15:30 +0000
committerHåvard Pettersen <havardpe@oath.com>2020-06-18 10:21:48 +0000
commit9b475a9b958ccf56a8c793021d21cdde09d39e15 (patch)
treed6e04e4ad2d8ed8d284447673e911fd9a7df24a8 /eval
parentd3b332d3d9772b4cdff30ad68c87d5a525c119eb (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.txt1
-rw-r--r--eval/src/tests/eval/multiply_add/CMakeLists.txt9
-rw-r--r--eval/src/tests/eval/multiply_add/multiply_add_test.cpp44
-rw-r--r--eval/src/vespa/eval/eval/test/eval_spec.cpp6
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; });