From: Shotaro Kawaguchi Date: Wed, 15 Jul 2015 08:21:35 +0000 (+0900) Subject: erasure code: shec performance optimization with SIMD instructions X-Git-Tag: v9.1.0~528^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=2ff6bcf5441a8f02f2288d19993293cd8809ad8f;p=ceph.git erasure code: shec performance optimization with SIMD instructions continued from https://github.com/ceph/ceph/pull/4689 Signed-off-by: Shotaro Kawaguchi --- diff --git a/src/erasure-code/shec/ErasureCodePluginSelectShec.cc b/src/erasure-code/shec/ErasureCodePluginSelectShec.cc new file mode 100644 index 00000000000..1bae15f6470 --- /dev/null +++ b/src/erasure-code/shec/ErasureCodePluginSelectShec.cc @@ -0,0 +1,99 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2013,2014 Cloudwatt + * Copyright (C) 2014 Red Hat + * Copyright (C) 2014,2015 FUJITSU LIMITED + * + * Author: Loic Dachary + * Author: Shotaro Kawaguchi + * Author: Takanori Nakao + * Author: Takeshi Miyamae + * + * This library 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; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include "ceph_ver.h" +#include "common/debug.h" +#include "arch/probe.h" +#include "arch/intel.h" +#include "arch/arm.h" +#include "erasure-code/ErasureCodePlugin.h" + +#define dout_subsys ceph_subsys_osd +#undef dout_prefix +#define dout_prefix _prefix(_dout) + +static ostream& _prefix(std::ostream* _dout) +{ + return *_dout << "ErasureCodePluginSelectShec: "; +} + +static string get_variant() { + ceph_arch_probe(); + + if (ceph_arch_intel_pclmul && + ceph_arch_intel_sse42 && + ceph_arch_intel_sse41 && + ceph_arch_intel_ssse3 && + ceph_arch_intel_sse3 && + ceph_arch_intel_sse2) { + return "sse4"; + } else if (ceph_arch_intel_ssse3 && + ceph_arch_intel_sse3 && + ceph_arch_intel_sse2) { + return "sse3"; + } else if (ceph_arch_neon) { + return "neon"; + } else { + return "generic"; + } +} + +class ErasureCodePluginSelectShec : public ErasureCodePlugin { +public: + virtual int factory(ErasureCodeProfile &profile, + ErasureCodeInterfaceRef *erasure_code, + ostream *ss) { + ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance(); + int ret; + string name = "shec"; + if (profile.count("shec-name")) + name = profile.find("shec-name")->second; + if (profile.count("shec-variant")) { + dout(10) << "shec-variant " + << profile.find("shec-variant")->second << dendl; + ret = instance.factory(name + "_" + profile.find("shec-variant")->second, + profile, erasure_code, ss); + } else { + string variant = get_variant(); + dout(10) << variant << " plugin" << dendl; + ret = instance.factory(name + "_" + variant, profile, erasure_code, ss); + } + return ret; + } +}; + +const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; } + +int __erasure_code_init(char *plugin_name, char *directory) +{ + ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance(); + string variant = get_variant(); + ErasureCodePlugin *plugin; + stringstream ss; + int r = instance.load(plugin_name + string("_") + variant, + directory, &plugin, &ss); + if (r) { + derr << ss.str() << dendl; + return r; + } + dout(10) << ss.str() << dendl; + return instance.add(plugin_name, new ErasureCodePluginSelectShec()); +} diff --git a/src/erasure-code/shec/ErasureCodeShec.cc b/src/erasure-code/shec/ErasureCodeShec.cc index ffd8e59c594..fc49e729835 100644 --- a/src/erasure-code/shec/ErasureCodeShec.cc +++ b/src/erasure-code/shec/ErasureCodeShec.cc @@ -247,7 +247,6 @@ int ErasureCodeShec::decode_chunks(const set &want_to_read, } avails[i] = 0; } else { - (*decoded)[i] = chunks.find(i)->second; avails[i] = 1; } if (i < k) diff --git a/src/erasure-code/shec/Makefile.am b/src/erasure-code/shec/Makefile.am index e4ca5f8e72f..1449a41ac23 100644 --- a/src/erasure-code/shec/Makefile.am +++ b/src/erasure-code/shec/Makefile.am @@ -1,6 +1,5 @@ # SHEC plugin - -libec_shec_la_SOURCES = \ +shec_sources = \ erasure-code/ErasureCode.cc \ erasure-code/shec/ErasureCodePluginShec.cc \ erasure-code/shec/ErasureCodeShec.cc \ @@ -22,6 +21,7 @@ libec_shec_la_SOURCES = \ erasure-code/jerasure/gf-complete/src/gf_w4.c \ erasure-code/jerasure/gf-complete/src/gf_rand.c \ erasure-code/jerasure/gf-complete/src/gf_w8.c + noinst_HEADERS += \ erasure-code/shec/ErasureCodeShec.h \ erasure-code/shec/ErasureCodeShecTableCache.h \ @@ -38,20 +38,125 @@ noinst_HEADERS += \ erasure-code/shec/ErasureCodePluginShec.cc: ./ceph_ver.h -libec_shec_la_CFLAGS = ${AM_CFLAGS} \ +libec_shec_generic_la_SOURCES = ${shec_sources} +libec_shec_generic_la_CFLAGS = ${AM_CFLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +libec_shec_generic_la_CXXFLAGS= ${AM_CXXFLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +libec_shec_generic_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS) +libec_shec_generic_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 +if LINUX +libec_shec_generic_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*' +endif + +erasure_codelib_LTLIBRARIES += libec_shec_generic.la + +libec_shec_neon_la_SOURCES = ${shec_sources} \ + erasure-code/jerasure/gf-complete/src/neon/gf_w4_neon.c \ + erasure-code/jerasure/gf-complete/src/neon/gf_w8_neon.c \ + erasure-code/jerasure/gf-complete/src/neon/gf_w16_neon.c \ + erasure-code/jerasure/gf-complete/src/neon/gf_w32_neon.c \ + erasure-code/jerasure/gf-complete/src/neon/gf_w64_neon.c +libec_shec_neon_la_CFLAGS = ${AM_CFLAGS} \ + ${ARM_NEON_FLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +libec_shec_neon_la_CXXFLAGS= ${AM_CXXFLAGS} \ + ${ARM_NEON_FLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +libec_shec_neon_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS) +libec_shec_neon_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 +if LINUX +libec_shec_neon_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*' +endif + +if HAVE_NEON +erasure_codelib_LTLIBRARIES += libec_shec_neon.la +endif + +libec_shec_sse3_la_SOURCES = ${shec_sources} +libec_shec_sse3_la_CFLAGS = ${AM_CFLAGS} \ + ${INTEL_SSE_FLAGS} \ + ${INTEL_SSE2_FLAGS} \ + ${INTEL_SSE3_FLAGS} \ + ${INTEL_SSSE3_FLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +libec_shec_sse3_la_CXXFLAGS= ${AM_CXXFLAGS} \ + ${INTEL_SSE_FLAGS} \ + ${INTEL_SSE2_FLAGS} \ + ${INTEL_SSE3_FLAGS} \ + ${INTEL_SSSE3_FLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +libec_shec_sse3_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS) +libec_shec_sse3_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 +if LINUX +libec_shec_sse3_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*' +endif + +if HAVE_SSSE3 +erasure_codelib_LTLIBRARIES += libec_shec_sse3.la +endif + +libec_shec_sse4_la_SOURCES = ${shec_sources} +libec_shec_sse4_la_CFLAGS = ${AM_CFLAGS} \ + ${INTEL_SSE_FLAGS} \ + ${INTEL_SSE2_FLAGS} \ + ${INTEL_SSE3_FLAGS} \ + ${INTEL_SSSE3_FLAGS} \ + ${INTEL_SSE4_1_FLAGS} \ + ${INTEL_SSE4_2_FLAGS} \ -I$(srcdir)/erasure-code/jerasure/jerasure/include \ -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ -I$(srcdir)/erasure-code/jerasure \ -I$(srcdir)/erasure-code/shec -libec_shec_la_CXXFLAGS= ${AM_CXXFLAGS} \ +libec_shec_sse4_la_CXXFLAGS= ${AM_CXXFLAGS} \ + ${INTEL_SSE_FLAGS} \ + ${INTEL_SSE2_FLAGS} \ + ${INTEL_SSE3_FLAGS} \ + ${INTEL_SSSE3_FLAGS} \ + ${INTEL_SSE4_1_FLAGS} \ + ${INTEL_SSE4_2_FLAGS} \ -I$(srcdir)/erasure-code/jerasure/jerasure/include \ -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ -I$(srcdir)/erasure-code/jerasure \ -I$(srcdir)/erasure-code/shec +libec_shec_sse4_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS) +libec_shec_sse4_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 +if LINUX +libec_shec_sse4_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*' +endif + +if HAVE_SSE4_PCLMUL +erasure_codelib_LTLIBRARIES += libec_shec_sse4.la +endif + +libec_shec_la_SOURCES = \ + erasure-code/shec/ErasureCodePluginSelectShec.cc +libec_shec_la_CFLAGS = ${AM_CFLAGS} +libec_shec_la_CXXFLAGS= ${AM_CXXFLAGS} libec_shec_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS) libec_shec_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 if LINUX libec_shec_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*' endif +erasure-code/shec/ErasureCodePluginSelectShec.cc: ./ceph_ver.h + erasure_codelib_LTLIBRARIES += libec_shec.la diff --git a/src/test/erasure-code/Makefile.am b/src/test/erasure-code/Makefile.am index f2d0d181611..ed0a014eccf 100644 --- a/src/test/erasure-code/Makefile.am +++ b/src/test/erasure-code/Makefile.am @@ -200,9 +200,17 @@ check_TESTPROGRAMS += unittest_erasure_code_plugin_lrc unittest_erasure_code_shec_SOURCES = \ test/erasure-code/TestErasureCodeShec.cc \ - ${libec_shec_la_SOURCES} -unittest_erasure_code_shec_CFLAGS = ${libec_shec_la_CFLAGS} -unittest_erasure_code_shec_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) + ${shec_sources} +unittest_erasure_code_shec_CFLAGS = ${libec_shec_la_CFLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +unittest_erasure_code_shec_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec unittest_erasure_code_shec_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL) if LINUX unittest_erasure_code_shec_LDADD += -ldl @@ -211,9 +219,17 @@ check_TESTPROGRAMS += unittest_erasure_code_shec unittest_erasure_code_shec_all_SOURCES = \ test/erasure-code/TestErasureCodeShec_all.cc \ - ${libec_shec_la_SOURCES} -unittest_erasure_code_shec_all_CFLAGS = ${libec_shec_la_CFLAGS} -unittest_erasure_code_shec_all_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) + ${shec_sources} +unittest_erasure_code_shec_all_CFLAGS = ${libec_shec_la_CFLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +unittest_erasure_code_shec_all_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec unittest_erasure_code_shec_all_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL) if LINUX unittest_erasure_code_shec_all_LDADD += -ldl @@ -222,9 +238,17 @@ check_TESTPROGRAMS += unittest_erasure_code_shec_all unittest_erasure_code_shec_thread_SOURCES = \ test/erasure-code/TestErasureCodeShec_thread.cc \ - ${libec_shec_la_SOURCES} -unittest_erasure_code_shec_thread_CFLAGS = ${libec_shec_la_CFLAGS} -unittest_erasure_code_shec_thread_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) + ${shec_sources} +unittest_erasure_code_shec_thread_CFLAGS = ${libec_shec_la_CFLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +unittest_erasure_code_shec_thread_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec unittest_erasure_code_shec_thread_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL) if LINUX unittest_erasure_code_shec_thread_LDADD += -ldl @@ -233,15 +257,64 @@ check_TESTPROGRAMS += unittest_erasure_code_shec_thread unittest_erasure_code_shec_arguments_SOURCES = \ test/erasure-code/TestErasureCodeShec_arguments.cc \ - ${libec_shec_la_SOURCES} -unittest_erasure_code_shec_arguments_CFLAGS = ${libec_shec_la_CFLAGS} -unittest_erasure_code_shec_arguments_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) + ${shec_sources} +unittest_erasure_code_shec_arguments_CFLAGS = ${libec_shec_la_CFLAGS} \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec +unittest_erasure_code_shec_arguments_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) \ + -I$(srcdir)/erasure-code/jerasure/jerasure/include \ + -I$(srcdir)/erasure-code/jerasure/gf-complete/include \ + -I$(srcdir)/erasure-code/jerasure \ + -I$(srcdir)/erasure-code/shec unittest_erasure_code_shec_arguments_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL) if LINUX unittest_erasure_code_shec_arguments_LDADD += -ldl endif check_TESTPROGRAMS += unittest_erasure_code_shec_arguments +unittest_erasure_code_plugin_shec_SOURCES = \ + test/erasure-code/TestErasureCodePluginShec.cc +unittest_erasure_code_plugin_shec_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS} +unittest_erasure_code_plugin_shec_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL) +if LINUX +unittest_erasure_code_plugin_shec_LDADD += -ldl +endif +check_TESTPROGRAMS += unittest_erasure_code_plugin_shec + +libec_test_shec_neon_la_SOURCES = test/erasure-code/TestShecPluginNEON.cc +test/erasure-code/TestShecPluginNEON.cc: ./ceph_ver.h +libec_test_shec_neon_la_CFLAGS = ${AM_CFLAGS} +libec_test_shec_neon_la_CXXFLAGS= ${AM_CXXFLAGS} +libec_test_shec_neon_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS) +libec_test_shec_neon_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*' +erasure_codelib_LTLIBRARIES += libec_test_shec_neon.la + +libec_test_shec_sse4_la_SOURCES = test/erasure-code/TestShecPluginSSE4.cc +test/erasure-code/TestShecPluginSSE4.cc: ./ceph_ver.h +libec_test_shec_sse4_la_CFLAGS = ${AM_CFLAGS} +libec_test_shec_sse4_la_CXXFLAGS= ${AM_CXXFLAGS} +libec_test_shec_sse4_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS) +libec_test_shec_sse4_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*' +erasure_codelib_LTLIBRARIES += libec_test_shec_sse4.la + +libec_test_shec_sse3_la_SOURCES = test/erasure-code/TestShecPluginSSE3.cc +test/erasure-code/TestShecPluginSSE3.cc: ./ceph_ver.h +libec_test_shec_sse3_la_CFLAGS = ${AM_CFLAGS} +libec_test_shec_sse3_la_CXXFLAGS= ${AM_CXXFLAGS} +libec_test_shec_sse3_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS) +libec_test_shec_sse3_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*' +erasure_codelib_LTLIBRARIES += libec_test_shec_sse3.la + +libec_test_shec_generic_la_SOURCES = test/erasure-code/TestShecPluginGeneric.cc +test/erasure-code/TestShecPluginGeneric.cc: ./ceph_ver.h +libec_test_shec_generic_la_CFLAGS = ${AM_CFLAGS} +libec_test_shec_generic_la_CXXFLAGS= ${AM_CXXFLAGS} +libec_test_shec_generic_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS) +libec_test_shec_generic_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*' +erasure_codelib_LTLIBRARIES += libec_test_shec_generic.la + unittest_erasure_code_example_SOURCES = \ erasure-code/ErasureCode.cc \ test/erasure-code/TestErasureCodeExample.cc diff --git a/src/test/erasure-code/TestErasureCodePluginShec.cc b/src/test/erasure-code/TestErasureCodePluginShec.cc new file mode 100644 index 00000000000..405aca2330a --- /dev/null +++ b/src/test/erasure-code/TestErasureCodePluginShec.cc @@ -0,0 +1,255 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2015 FUJITSU LIMITED + * + * Author: Shotaro Kawaguchi + * Author: Takanori Nakao + * Author: Takeshi Miyamae + * + * This library 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; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include +#include "arch/probe.h" +#include "arch/intel.h" +#include "arch/arm.h" +#include "global/global_init.h" +#include "erasure-code/ErasureCodePlugin.h" +#include "common/ceph_argparse.h" +#include "global/global_context.h" +#include "gtest/gtest.h" + +TEST(ErasureCodePlugin, factory) +{ + ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance(); + map profile; + profile["directory"] = ".libs"; + { + ErasureCodeInterfaceRef erasure_code; + EXPECT_FALSE(erasure_code); + EXPECT_EQ(0, instance.factory("shec", profile, + &erasure_code, &cerr)); + EXPECT_TRUE(erasure_code); + } + const char *techniques[] = { + "single", + "multiple", + 0 + }; + for(const char **technique = techniques; *technique; technique++) { + ErasureCodeInterfaceRef erasure_code; + profile["directory"] = ".libs"; + profile["technique"] = *technique; + EXPECT_FALSE(erasure_code); + EXPECT_EQ(0, instance.factory("shec", profile, + &erasure_code, &cerr)); + EXPECT_TRUE(erasure_code); + } +} + +TEST(ErasureCodePlugin, select) +{ + ceph_arch_probe(); + // save probe results + int arch_intel_pclmul = ceph_arch_intel_pclmul; + int arch_intel_sse42 = ceph_arch_intel_sse42; + int arch_intel_sse41 = ceph_arch_intel_sse41; + int arch_intel_ssse3 = ceph_arch_intel_ssse3; + int arch_intel_sse3 = ceph_arch_intel_sse3; + int arch_intel_sse2 = ceph_arch_intel_sse2; + int arch_neon = ceph_arch_neon; + + ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance(); + map profile; + // load test plugins instead of actual plugins to assert the desired side effect + // happens + profile["shec-name"] = "test_shec"; + profile["directory"] = ".libs"; + profile["technique"] = "multiple"; + + // all features are available, load the SSE4 plugin + { + ceph_arch_intel_pclmul = 1; + ceph_arch_intel_sse42 = 1; + ceph_arch_intel_sse41 = 1; + ceph_arch_intel_ssse3 = 1; + ceph_arch_intel_sse3 = 1; + ceph_arch_intel_sse2 = 1; + ceph_arch_neon = 0; + + ErasureCodeInterfaceRef erasure_code; + int sse4_side_effect = -444; + EXPECT_EQ(sse4_side_effect, instance.factory("shec", profile, + &erasure_code, &cerr)); + } + // pclmul is missing, load the SSE3 plugin + { + ceph_arch_intel_pclmul = 0; + ceph_arch_intel_sse42 = 1; + ceph_arch_intel_sse41 = 1; + ceph_arch_intel_ssse3 = 1; + ceph_arch_intel_sse3 = 1; + ceph_arch_intel_sse2 = 1; + ceph_arch_neon = 0; + + ErasureCodeInterfaceRef erasure_code; + int sse3_side_effect = -333; + EXPECT_EQ(sse3_side_effect, instance.factory("shec", profile, + &erasure_code, &cerr)); + } + // pclmul and sse3 are missing, load the generic plugin + { + ceph_arch_intel_pclmul = 0; + ceph_arch_intel_sse42 = 1; + ceph_arch_intel_sse41 = 1; + ceph_arch_intel_ssse3 = 1; + ceph_arch_intel_sse3 = 0; + ceph_arch_intel_sse2 = 1; + ceph_arch_neon = 0; + + ErasureCodeInterfaceRef erasure_code; + int generic_side_effect = -111; + EXPECT_EQ(generic_side_effect, instance.factory("shec", profile, + &erasure_code, &cerr)); + } + // neon is set, load the neon plugin + { + ceph_arch_intel_pclmul = 0; + ceph_arch_intel_sse42 = 0; + ceph_arch_intel_sse41 = 0; + ceph_arch_intel_ssse3 = 0; + ceph_arch_intel_sse3 = 0; + ceph_arch_intel_sse2 = 0; + ceph_arch_neon = 1; + + ErasureCodeInterfaceRef erasure_code; + int generic_side_effect = -555; + EXPECT_EQ(generic_side_effect, instance.factory("shec", profile, + &erasure_code, &cerr)); + } + + + // restore probe results + ceph_arch_intel_pclmul = arch_intel_pclmul; + ceph_arch_intel_sse42 = arch_intel_sse42; + ceph_arch_intel_sse41 = arch_intel_sse41; + ceph_arch_intel_ssse3 = arch_intel_ssse3; + ceph_arch_intel_sse3 = arch_intel_sse3; + ceph_arch_intel_sse2 = arch_intel_sse2; + ceph_arch_neon = arch_neon; +} + +TEST(ErasureCodePlugin, sse) +{ + ceph_arch_probe(); + bool sse4 = ceph_arch_intel_pclmul && + ceph_arch_intel_sse42 && ceph_arch_intel_sse41 && + ceph_arch_intel_ssse3 && ceph_arch_intel_sse3 && + ceph_arch_intel_sse2; + bool sse3 = ceph_arch_intel_ssse3 && ceph_arch_intel_sse3 && + ceph_arch_intel_sse2; + vector sse_variants; + sse_variants.push_back("generic"); + if (!sse3) + cerr << "SKIP sse3 plugin testing because CPU does not support it\n"; + else + sse_variants.push_back("sse3"); + if (!sse4) + cerr << "SKIP sse4 plugin testing because CPU does not support it\n"; + else + sse_variants.push_back("sse4"); + +#define LARGE_ENOUGH 2048 + bufferptr in_ptr(buffer::create_page_aligned(LARGE_ENOUGH)); + in_ptr.zero(); + in_ptr.set_length(0); + const char *payload = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + in_ptr.append(payload, strlen(payload)); + bufferlist in; + in.push_front(in_ptr); + + ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance(); + map profile; + profile["directory"] = ".libs"; + profile["technique"] = "multiple"; + profile["k"] = "2"; + profile["m"] = "1"; + profile["c"] = "1"; + for (vector::iterator sse_variant = sse_variants.begin(); + sse_variant != sse_variants.end(); + ++sse_variant) { + // + // load the plugin variant + // + ErasureCodeInterfaceRef erasure_code; + EXPECT_FALSE(erasure_code); + EXPECT_EQ(0, instance.factory("shec_" + *sse_variant, profile, + &erasure_code, &cerr)); + EXPECT_TRUE(erasure_code); + + // + // encode + // + int want_to_encode[] = { 0, 1, 2 }; + map encoded; + EXPECT_EQ(0, erasure_code->encode(set(want_to_encode, want_to_encode+3), + in, + &encoded)); + EXPECT_EQ(3u, encoded.size()); + unsigned length = encoded[0].length(); + EXPECT_EQ(0, strncmp(encoded[0].c_str(), in.c_str(), length)); + EXPECT_EQ(0, strncmp(encoded[1].c_str(), in.c_str() + length, + in.length() - length)); + + // + // decode with reconstruction + // + map degraded = encoded; + degraded.erase(1); + EXPECT_EQ(2u, degraded.size()); + int want_to_decode[] = { 0, 1 }; + map decoded; + EXPECT_EQ(0, erasure_code->decode(set(want_to_decode, want_to_decode+2), + degraded, + &decoded)); + EXPECT_EQ(3u, decoded.size()); + EXPECT_EQ(length, decoded[0].length()); + EXPECT_EQ(0, strncmp(decoded[0].c_str(), in.c_str(), length)); + EXPECT_EQ(0, strncmp(decoded[1].c_str(), in.c_str() + length, + in.length() - length)); + + } +} + +int main(int argc, char **argv) +{ + vector args; + argv_to_vec(argc, (const char **)argv, args); + + global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); + common_init_finish(g_ceph_context); + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +/* + * Local Variables: + * compile-command: "cd ../.. ; make -j4 && + * make unittest_erasure_code_plugin_shec && + * valgrind --tool=memcheck ./unittest_erasure_code_plugin_shec \ + * --gtest_filter=*.* --log-to-stderr=true --debug-osd=20" + * End: + */ diff --git a/src/test/erasure-code/TestShecPluginGeneric.cc b/src/test/erasure-code/TestShecPluginGeneric.cc new file mode 100644 index 00000000000..0bd063b094c --- /dev/null +++ b/src/test/erasure-code/TestShecPluginGeneric.cc @@ -0,0 +1,29 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2014 Cloudwatt + * Copyright (C) 2014 Red Hat + * Copyright (C) 2015 FUJITSU LIMITED + * + * Author: Loic Dachary + * Author: Shotaro Kawaguchi + * Author: Takanori Nakao + * Author: Takeshi Miyamae + * + * This library 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; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include "ceph_ver.h" + +extern "C" const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; } + +extern "C" int __erasure_code_init(char *plugin_name, char *directory) +{ + return -111; +} diff --git a/src/test/erasure-code/TestShecPluginNEON.cc b/src/test/erasure-code/TestShecPluginNEON.cc new file mode 100644 index 00000000000..373f5eb4b47 --- /dev/null +++ b/src/test/erasure-code/TestShecPluginNEON.cc @@ -0,0 +1,29 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2014 Cloudwatt + * Copyright (C) 2014 Red Hat + * Copyright (C) 2015 FUJITSU LIMITED + * + * Author: Loic Dachary + * Author: Shotaro Kawaguchi + * Author: Takanori Nakao + * Author: Takeshi Miyamae + * + * This library 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; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include "ceph_ver.h" + +extern "C" const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; } + +extern "C" int __erasure_code_init(char *plugin_name, char *directory) +{ + return -555; +} diff --git a/src/test/erasure-code/TestShecPluginSSE3.cc b/src/test/erasure-code/TestShecPluginSSE3.cc new file mode 100644 index 00000000000..220ea7b6397 --- /dev/null +++ b/src/test/erasure-code/TestShecPluginSSE3.cc @@ -0,0 +1,29 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2014 Cloudwatt + * Copyright (C) 2014 Red Hat + * Copyright (C) 2015 FUJITSU LIMITED + * + * Author: Loic Dachary + * Author: Shotaro Kawaguchi + * Author: Takanori Nakao + * Author: Takeshi Miyamae + * + * This library 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; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include "ceph_ver.h" + +extern "C" const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; } + +extern "C" int __erasure_code_init(char *plugin_name, char *directory) +{ + return -333; +} diff --git a/src/test/erasure-code/TestShecPluginSSE4.cc b/src/test/erasure-code/TestShecPluginSSE4.cc new file mode 100644 index 00000000000..ef8e8410c61 --- /dev/null +++ b/src/test/erasure-code/TestShecPluginSSE4.cc @@ -0,0 +1,29 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2014 Cloudwatt + * Copyright (C) 2014 Red Hat + * Copyright (C) 2015 FUJITSU LIMITED + * + * Author: Loic Dachary + * Author: Shotaro Kawaguchi + * Author: Takanori Nakao + * Author: Takeshi Miyamae + * + * This library 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; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include "ceph_ver.h" + +extern "C" const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; } + +extern "C" int __erasure_code_init(char *plugin_name, char *directory) +{ + return -444; +}