<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file peer.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Peer Network test functions.
 */

#include <boost/test/unit_test.hpp>
#include <chrono>
#include <thread>
#include <libp2p/Host.h>
using namespace std;
using namespace dev;
using namespace dev::p2p;

BOOST_AUTO_TEST_SUITE(p2p)

BOOST_AUTO_TEST_CASE(host)
{
	NetworkPreferences host1prefs(30301, "127.0.0.1", true, true);
	NetworkPreferences host2prefs(30302, "127.0.0.1", true, true);

	Host host1("Test", host1prefs);
	host1.start();

	Host host2("Test", host2prefs);
	auto node2 = host2.id();
	host2.start();

	host1.addNode(node2, "127.0.0.1", host2prefs.listenPort, host2prefs.listenPort);

	this_thread::sleep_for(chrono::seconds(1));

	BOOST_REQUIRE_EQUAL(host1.peerCount(), 1);
	BOOST_REQUIRE_EQUAL(host2.peerCount(), host1.peerCount());
}

BOOST_AUTO_TEST_CASE(save_nodes)
{
	std::list<Host*> hosts;
	for (auto i:{0,1,2,3,4,5})
	{
		Host* h = new Host("Test", NetworkPreferences(30300 + i, "127.0.0.1", true, true));
		// starting host is required so listenport is available
		h->start();
		while (!h->isStarted())
			this_thread::sleep_for(chrono::milliseconds(2));
		hosts.push_back(h);
	}

	Host& host = *hosts.front();
	for (auto const& h: hosts)
		host.addNode(h->id(), "127.0.0.1", h->listenPort(), h->listenPort());

	Host& host2 = *hosts.back();
	for (auto const& h: hosts)
		host2.addNode(h->id(), "127.0.0.1", h->listenPort(), h->listenPort());

	this_thread::sleep_for(chrono::milliseconds(1000));
	bytes firstHostNetwork(host.saveNetwork());
	bytes secondHostNetwork(host.saveNetwork());

	BOOST_REQUIRE_EQUAL(sha3(firstHostNetwork), sha3(secondHostNetwork));

	BOOST_CHECK_EQUAL(host.peerCount(), 5);
	BOOST_CHECK_EQUAL(host2.peerCount(), 5);

	RLP r(firstHostNetwork);
	BOOST_REQUIRE(r.itemCount() == 3);
	BOOST_REQUIRE(r[0].toInt<int>() == 1);
	BOOST_REQUIRE_EQUAL(r[1].toBytes().size(), 32); // secret
	BOOST_REQUIRE_EQUAL(r[2].itemCount(), 5);
}

BOOST_AUTO_TEST_SUITE_END()

int peerTest(int argc, char** argv)
{
	Public remoteAlias;
	short listenPort = 30303;
	string remoteHost;
	short remotePort = 30303;

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if (arg == "-l" && i + 1 < argc)
			listenPort = (short)atoi(argv[++i]);
		else if (arg == "-r" && i + 1 < argc)
			remoteHost = argv[++i];
		else if (arg == "-p" && i + 1 < argc)
			remotePort = (short)atoi(argv[++i]);
		else if (arg == "-ra" && i + 1 < argc)
			remoteAlias = Public(dev::fromHex(argv[++i]));
		else
			remoteHost = argv[i];
	}

	Host ph("Test", NetworkPreferences(listenPort));

	if (!remoteHost.empty() && !remoteAlias)
		ph.addNode(remoteAlias, remoteHost, remotePort, remotePort);

	this_thread::sleep_for(chrono::milliseconds(200));

	return 0;
}

<commit_msg>separate packet type. add coding.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file peer.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Peer Network test functions.
 */

#include <boost/test/unit_test.hpp>
#include <chrono>
#include <thread>
#include <libp2p/Host.h>
using namespace std;
using namespace dev;
using namespace dev::p2p;

BOOST_AUTO_TEST_SUITE(p2p)

BOOST_AUTO_TEST_CASE(host)
{
	auto oldLogVerbosity = g_logVerbosity;
	g_logVerbosity = 10;

	NetworkPreferences host1prefs(30301, "127.0.0.1", true, true);
	NetworkPreferences host2prefs(30302, "127.0.0.1", true, true);

	Host host1("Test", host1prefs);
	host1.start();

	Host host2("Test", host2prefs);
	auto node2 = host2.id();
	host2.start();

	host1.addNode(node2, "127.0.0.1", host2prefs.listenPort, host2prefs.listenPort);

	this_thread::sleep_for(chrono::seconds(3));

	auto host1peerCount = host1.peerCount();
	auto host2peerCount = host2.peerCount();
	BOOST_REQUIRE_EQUAL(host1peerCount, 1);
	BOOST_REQUIRE_EQUAL(host2peerCount, 1);

	g_logVerbosity = oldLogVerbosity;
}

BOOST_AUTO_TEST_CASE(save_nodes)
{
	std::list<Host*> hosts;
	for (auto i:{0,1,2,3,4,5})
	{
		Host* h = new Host("Test", NetworkPreferences(30300 + i, "127.0.0.1", true, true));
		// starting host is required so listenport is available
		h->start();
		while (!h->isStarted())
			this_thread::sleep_for(chrono::milliseconds(2));
		hosts.push_back(h);
	}

	Host& host = *hosts.front();
	for (auto const& h: hosts)
		host.addNode(h->id(), "127.0.0.1", h->listenPort(), h->listenPort());

	Host& host2 = *hosts.back();
	for (auto const& h: hosts)
		host2.addNode(h->id(), "127.0.0.1", h->listenPort(), h->listenPort());

	this_thread::sleep_for(chrono::milliseconds(2000));
	bytes firstHostNetwork(host.saveNetwork());
	bytes secondHostNetwork(host.saveNetwork());

	BOOST_REQUIRE_EQUAL(sha3(firstHostNetwork), sha3(secondHostNetwork));

	BOOST_CHECK_EQUAL(host.peerCount(), 5);
	BOOST_CHECK_EQUAL(host2.peerCount(), 5);

	RLP r(firstHostNetwork);
	BOOST_REQUIRE(r.itemCount() == 3);
	BOOST_REQUIRE(r[0].toInt<int>() == 1);
	BOOST_REQUIRE_EQUAL(r[1].toBytes().size(), 32); // secret
	BOOST_REQUIRE_EQUAL(r[2].itemCount(), 5);
}

BOOST_AUTO_TEST_SUITE_END()

int peerTest(int argc, char** argv)
{
	Public remoteAlias;
	short listenPort = 30303;
	string remoteHost;
	short remotePort = 30303;

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if (arg == "-l" && i + 1 < argc)
			listenPort = (short)atoi(argv[++i]);
		else if (arg == "-r" && i + 1 < argc)
			remoteHost = argv[++i];
		else if (arg == "-p" && i + 1 < argc)
			remotePort = (short)atoi(argv[++i]);
		else if (arg == "-ra" && i + 1 < argc)
			remoteAlias = Public(dev::fromHex(argv[++i]));
		else
			remoteHost = argv[i];
	}

	Host ph("Test", NetworkPreferences(listenPort));

	if (!remoteHost.empty() && !remoteAlias)
		ph.addNode(remoteAlias, remoteHost, remotePort, remotePort);

	this_thread::sleep_for(chrono::milliseconds(200));

	return 0;
}

<|endoftext|>


<commit_before>#ifndef HELPER_HXX
#define HELPER_HXX

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <opengm/python/opengmpython.hxx>
#include <opengm/python/converter.hxx>
#include <opengm/python/numpyview.hxx>

#include <opengm/inference/icm.hxx>
#include <opengm/inference/lazyflipper.hxx>
#include <opengm/inference/self_fusion.hxx>
#include <opengm/learning/gridsearch-learning.hxx>
#include <opengm/inference/messagepassing/messagepassing.hxx>

#ifdef WITH_CPLEX
#include <opengm/inference/lpcplex.hxx>
#endif

#ifdef WITH_QPBO
#include <opengm/inference/external/qpbo.hxx>
#include <opengm/inference/reducedinference.hxx>
#endif

#ifdef WITH_TRWS
#include <opengm/inference/external/trws.hxx>
#endif

namespace opengm{

template<class LEARNER>
class LearnerInferenceSuite: public boost::python::def_visitor<LearnerInferenceSuite<LEARNER> >{
public:
    friend class boost::python::def_visitor_access;

    LearnerInferenceSuite(){

    }

    template<class INF>
    static void pyLearn_Inf(LEARNER & learner, const typename INF::Parameter & param)
    {
        learner. template learn<INF>(param);
    }

    #ifdef WITH_QPBO
    template<class INF>
    static void pyLearn_ReducedInf(
        LEARNER & learner,
        const typename INF::Parameter & param,
        const bool persistency,
        const bool tentacles,
        const bool connectedComponents
    )
    {

        typedef typename INF::GraphicalModelType GmType;
        typedef typename opengm::ReducedInferenceHelper<GmType>::InfGmType RedInfGm;

        // rebind the inference to the RedInfGm
        typedef typename INF:: template RebindGm<RedInfGm>::type RedInfRebindInf;

        typedef typename RedInfRebindInf::Parameter RedInfRebindInfParam;
        typedef opengm::ReducedInference<GmType, opengm::Minimizer, RedInfRebindInf> RedInf;
        typedef typename RedInf::Parameter RedInfParam;

        RedInfRebindInfParam redInfRebindInfParam(param);

        RedInfParam redInfPara;
        redInfPara.subParameter_ = redInfRebindInfParam;
        redInfPara.Persistency_ = persistency;
        redInfPara.Tentacle_ = tentacles;
        redInfPara.ConnectedComponents_ = connectedComponents;

        learner. template learn<RedInf>(redInfPara);
    }
    #endif

    #ifdef WITH_QPBO
    template<class INF>
    static void pyLearn_ReducedInfSelfFusion(
        LEARNER & learner,
        const typename INF::Parameter & param,
        const bool persistency,
        const bool tentacles,
        const bool connectedComponents
    )
    {

        typedef typename INF::GraphicalModelType GmType;
        typedef typename opengm::ReducedInferenceHelper<GmType>::InfGmType RedInfGm;

        // rebind the inference to the RedInfGm
        typedef typename INF:: template RebindGm<RedInfGm>::type RedInfRebindInf;

        typedef typename RedInfRebindInf::Parameter RedInfRebindInfParam;
        typedef opengm::ReducedInference<GmType, opengm::Minimizer, RedInfRebindInf> RedInf;
        typedef typename RedInf::Parameter RedInfParam;

        RedInfRebindInfParam redInfRebindInfParam(param);

        RedInfParam redInfPara;
        redInfPara.subParameter_ = redInfRebindInfParam;
        redInfPara.Persistency_ = persistency;
        redInfPara.Tentacle_ = tentacles;
        redInfPara.ConnectedComponents_ = connectedComponents;

        typedef opengm::SelfFusion<RedInf> SelfFusionInf;
        typedef typename SelfFusionInf::Parameter SelfFusionInfParam;
        SelfFusionInfParam sfParam;

        sfParam.infParam_ = redInfPara;
        sfParam.fuseNth_ = 10;
        sfParam.maxSubgraphSize_ = 2;
        sfParam.reducedInf_ = true;
        sfParam.tentacles_ = false;
        sfParam.connectedComponents_ = true;
        sfParam.fusionTimeLimit_ = 100.0;
        sfParam.numStopIt_ = 10.0;
        sfParam.fusionSolver_ = SelfFusionInf::QpboFusion;

        learner. template learn<SelfFusionInf>(sfParam);
    }
    #endif

    template<class INF>
    static void pyLearn_SelfFusion(
        LEARNER & learner,
        const typename INF::Parameter & param,
        const size_t fuseNth,
        const std::string & fusionSolver,
        const UInt64Type maxSubgraphSize,
        const bool reducedInf,
        const bool connectedComponents,
        const double fusionTimeLimit,
        const size_t numStopIt
    )
    {

        typedef typename INF::GraphicalModelType GmType;

        typedef opengm::SelfFusion<INF> SelfFusionInf;
        typedef typename SelfFusionInf::Parameter SelfFusionInfParam;

        SelfFusionInfParam sfParam;

        if(fusionSolver ==std::string("qpbo")){
            sfParam.fusionSolver_ = SelfFusionInf::QpboFusion;
        }
        else if(fusionSolver ==std::string("cplex")){
            sfParam.fusionSolver_ = SelfFusionInf::CplexFusion;
        }
        else if(fusionSolver ==std::string("lf")){
            sfParam.fusionSolver_ = SelfFusionInf::LazyFlipperFusion;
        }

        sfParam.infParam_ = param;
        sfParam.fuseNth_ = fuseNth;
        sfParam.maxSubgraphSize_ = maxSubgraphSize;
        sfParam.reducedInf_ = reducedInf;
        sfParam.tentacles_ = false;
        sfParam.connectedComponents_ = connectedComponents;
        sfParam.fusionTimeLimit_ = fusionTimeLimit;
        sfParam.numStopIt_ = numStopIt;

        learner. template learn<SelfFusionInf>(sfParam);
    }

    template <class classT>
    void visit(classT& c) const{
        // SOME INFERENCE METHODS
        typedef typename LEARNER::GMType GMType;
        typedef typename LEARNER::Parameter PyLearnerParam;
        typedef typename LEARNER::DatasetType DatasetType;
        typedef opengm::Minimizer ACC;

        typedef opengm::ICM<GMType, ACC> IcmInf;
        typedef opengm::LazyFlipper<GMType, ACC> LazyFlipperInf;
        typedef opengm::BeliefPropagationUpdateRules<GMType, ACC> UpdateRulesType;
        typedef opengm::MessagePassing<GMType, ACC, UpdateRulesType, opengm::MaxDistance> BpInf;

        #ifdef WITH_CPLEX
            typedef opengm::LPCplex<GMType, ACC> Cplex;
        #endif

        #ifdef WITH_QPBO
            typedef opengm::external::QPBO<GMType>  QpboExternal;
        #endif

        #ifdef WITH_TRWS
            typedef opengm::external::TRWS<GMType>  TrwsExternal;
        #endif

        c
            .def("_learn",&pyLearn_Inf<IcmInf>)
            .def("_learn",&pyLearn_Inf<LazyFlipperInf>)
            .def("_learn",&pyLearn_Inf<BpInf>)
            #ifdef WITH_CPLEX
            .def("_learn",&pyLearn_Inf<Cplex>)
            #endif
            #ifdef WITH_QPBO
            .def("_learn",&pyLearn_Inf<QpboExternal>)
            #endif
            #ifdef WITH_TRWS
            .def("_learn",&pyLearn_Inf<TrwsExternal>)
            #endif

            // REDUCED INFERENCE
            #ifdef WITH_QPBO
                .def("_learnReducedInf",&pyLearn_ReducedInf<LazyFlipperInf>)
                #ifdef WITH_TRWS
                .def("_learnReducedInf",&pyLearn_ReducedInf<TrwsExternal>)
                #endif
                #ifdef WITH_CPLEX
                .def("_learnReducedInf",&pyLearn_ReducedInf<Cplex>)
                #endif
            #endif

            // SELF FUSION
            #ifdef WITH_TRWS
            .def("_learnSelfFusion",&pyLearn_SelfFusion<TrwsExternal>)
            #endif

            // REDUCED INFERNCE SELF FUSION
            #ifdef WITH_TRWS
            .def("_learnReducedInfSelfFusion",&pyLearn_ReducedInfSelfFusion<TrwsExternal>)
            #endif
        ;
    }
};

template<class DS>
class DatasetInferenceSuite: public boost::python::def_visitor<DatasetInferenceSuite<DS> >{
public:
   friend class boost::python::def_visitor_access;

   DatasetInferenceSuite(){

   }

   template<class INF>
   static typename DS::ValueType pyGetLossWithInf(DS & ds, const typename INF::Parameter & param, const size_t i)
   {
       return ds. template getLoss<INF>(param, i);
   }

   template<class INF>
   static typename DS::ValueType pyGetTotalLossWithInf(DS & ds, const typename INF::Parameter & param)
   {
       return ds. template getTotalLoss<INF>(param);
   }

   template <class classT>
   void visit(classT& c) const{
       // SOME INFERENCE METHODS
       typedef typename DS::GMType GMType;
       typedef opengm::Minimizer ACC;

       typedef opengm::ICM<GMType, ACC> IcmInf;
       typedef opengm::LazyFlipper<GMType, ACC> LazyFlipperInf;
       typedef opengm::BeliefPropagationUpdateRules<GMType, ACC> UpdateRulesType;
       typedef opengm::MessagePassing<GMType, ACC, UpdateRulesType, opengm::MaxDistance> BpInf;

#ifdef WITH_CPLEX
       typedef opengm::LPCplex<GMType, ACC> Cplex;
#endif
#ifdef WITH_QPBO
       typedef opengm::external::QPBO<GMType>  QpboExternal;
#endif
#ifdef WITH_TRWS
       typedef opengm::external::TRWS<GMType>  TrwsExternal;
#endif

      c
          .def("_getLoss",&pyGetLossWithInf<IcmInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<IcmInf>)
          .def("_getLoss",&pyGetLossWithInf<LazyFlipperInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<LazyFlipperInf>)
          .def("_getLoss",&pyGetLossWithInf<BpInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<BpInf>)
#ifdef WITH_CPLEX
          .def("_getLoss",&pyGetLossWithInf<Cplex>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<Cplex>)
#endif
#ifdef WITH_QPBO
          .def("_getLoss",&pyGetLossWithInf<QpboExternal>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<QpboExternal>)
#endif
#ifdef WITH_TRWS
          .def("_getLoss",&pyGetLossWithInf<TrwsExternal>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<TrwsExternal>)
#endif
      ;
   }
};

} // namespace opengm

#endif // HELPER_HXX

<commit_msg>Only build SelfFusion if QPBO is enabled<commit_after>#ifndef HELPER_HXX
#define HELPER_HXX

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <opengm/python/opengmpython.hxx>
#include <opengm/python/converter.hxx>
#include <opengm/python/numpyview.hxx>

#include <opengm/inference/icm.hxx>
#include <opengm/inference/lazyflipper.hxx>
#include <opengm/inference/self_fusion.hxx>
#include <opengm/learning/gridsearch-learning.hxx>
#include <opengm/inference/messagepassing/messagepassing.hxx>

#ifdef WITH_CPLEX
#include <opengm/inference/lpcplex.hxx>
#endif

#ifdef WITH_QPBO
#include <opengm/inference/external/qpbo.hxx>
#include <opengm/inference/reducedinference.hxx>
#endif

#ifdef WITH_TRWS
#include <opengm/inference/external/trws.hxx>
#endif

namespace opengm{

template<class LEARNER>
class LearnerInferenceSuite: public boost::python::def_visitor<LearnerInferenceSuite<LEARNER> >{
public:
    friend class boost::python::def_visitor_access;

    LearnerInferenceSuite(){

    }

    template<class INF>
    static void pyLearn_Inf(LEARNER & learner, const typename INF::Parameter & param)
    {
        learner. template learn<INF>(param);
    }

    #ifdef WITH_QPBO
    template<class INF>
    static void pyLearn_ReducedInf(
        LEARNER & learner,
        const typename INF::Parameter & param,
        const bool persistency,
        const bool tentacles,
        const bool connectedComponents
    )
    {

        typedef typename INF::GraphicalModelType GmType;
        typedef typename opengm::ReducedInferenceHelper<GmType>::InfGmType RedInfGm;

        // rebind the inference to the RedInfGm
        typedef typename INF:: template RebindGm<RedInfGm>::type RedInfRebindInf;

        typedef typename RedInfRebindInf::Parameter RedInfRebindInfParam;
        typedef opengm::ReducedInference<GmType, opengm::Minimizer, RedInfRebindInf> RedInf;
        typedef typename RedInf::Parameter RedInfParam;

        RedInfRebindInfParam redInfRebindInfParam(param);

        RedInfParam redInfPara;
        redInfPara.subParameter_ = redInfRebindInfParam;
        redInfPara.Persistency_ = persistency;
        redInfPara.Tentacle_ = tentacles;
        redInfPara.ConnectedComponents_ = connectedComponents;

        learner. template learn<RedInf>(redInfPara);
    }
    #endif

    #ifdef WITH_QPBO
    template<class INF>
    static void pyLearn_ReducedInfSelfFusion(
        LEARNER & learner,
        const typename INF::Parameter & param,
        const bool persistency,
        const bool tentacles,
        const bool connectedComponents
    )
    {

        typedef typename INF::GraphicalModelType GmType;
        typedef typename opengm::ReducedInferenceHelper<GmType>::InfGmType RedInfGm;

        // rebind the inference to the RedInfGm
        typedef typename INF:: template RebindGm<RedInfGm>::type RedInfRebindInf;

        typedef typename RedInfRebindInf::Parameter RedInfRebindInfParam;
        typedef opengm::ReducedInference<GmType, opengm::Minimizer, RedInfRebindInf> RedInf;
        typedef typename RedInf::Parameter RedInfParam;

        RedInfRebindInfParam redInfRebindInfParam(param);

        RedInfParam redInfPara;
        redInfPara.subParameter_ = redInfRebindInfParam;
        redInfPara.Persistency_ = persistency;
        redInfPara.Tentacle_ = tentacles;
        redInfPara.ConnectedComponents_ = connectedComponents;

        typedef opengm::SelfFusion<RedInf> SelfFusionInf;
        typedef typename SelfFusionInf::Parameter SelfFusionInfParam;
        SelfFusionInfParam sfParam;

        sfParam.infParam_ = redInfPara;
        sfParam.fuseNth_ = 10;
        sfParam.maxSubgraphSize_ = 2;
        sfParam.reducedInf_ = true;
        sfParam.tentacles_ = false;
        sfParam.connectedComponents_ = true;
        sfParam.fusionTimeLimit_ = 100.0;
        sfParam.numStopIt_ = 10.0;
        sfParam.fusionSolver_ = SelfFusionInf::QpboFusion;

        learner. template learn<SelfFusionInf>(sfParam);
    }
    #endif

    template<class INF>
    static void pyLearn_SelfFusion(
        LEARNER & learner,
        const typename INF::Parameter & param,
        const size_t fuseNth,
        const std::string & fusionSolver,
        const UInt64Type maxSubgraphSize,
        const bool reducedInf,
        const bool connectedComponents,
        const double fusionTimeLimit,
        const size_t numStopIt
    )
    {

        typedef typename INF::GraphicalModelType GmType;

        typedef opengm::SelfFusion<INF> SelfFusionInf;
        typedef typename SelfFusionInf::Parameter SelfFusionInfParam;

        SelfFusionInfParam sfParam;

        if(fusionSolver ==std::string("qpbo")){
            sfParam.fusionSolver_ = SelfFusionInf::QpboFusion;
        }
        else if(fusionSolver ==std::string("cplex")){
            sfParam.fusionSolver_ = SelfFusionInf::CplexFusion;
        }
        else if(fusionSolver ==std::string("lf")){
            sfParam.fusionSolver_ = SelfFusionInf::LazyFlipperFusion;
        }

        sfParam.infParam_ = param;
        sfParam.fuseNth_ = fuseNth;
        sfParam.maxSubgraphSize_ = maxSubgraphSize;
        sfParam.reducedInf_ = reducedInf;
        sfParam.tentacles_ = false;
        sfParam.connectedComponents_ = connectedComponents;
        sfParam.fusionTimeLimit_ = fusionTimeLimit;
        sfParam.numStopIt_ = numStopIt;

        learner. template learn<SelfFusionInf>(sfParam);
    }

    template <class classT>
    void visit(classT& c) const{
        // SOME INFERENCE METHODS
        typedef typename LEARNER::GMType GMType;
        typedef typename LEARNER::Parameter PyLearnerParam;
        typedef typename LEARNER::DatasetType DatasetType;
        typedef opengm::Minimizer ACC;

        typedef opengm::ICM<GMType, ACC> IcmInf;
        typedef opengm::LazyFlipper<GMType, ACC> LazyFlipperInf;
        typedef opengm::BeliefPropagationUpdateRules<GMType, ACC> UpdateRulesType;
        typedef opengm::MessagePassing<GMType, ACC, UpdateRulesType, opengm::MaxDistance> BpInf;

        #ifdef WITH_CPLEX
            typedef opengm::LPCplex<GMType, ACC> Cplex;
        #endif

        #ifdef WITH_QPBO
            typedef opengm::external::QPBO<GMType>  QpboExternal;
        #endif

        #ifdef WITH_TRWS
            typedef opengm::external::TRWS<GMType>  TrwsExternal;
        #endif

        c
            .def("_learn",&pyLearn_Inf<IcmInf>)
            .def("_learn",&pyLearn_Inf<LazyFlipperInf>)
            .def("_learn",&pyLearn_Inf<BpInf>)
            #ifdef WITH_CPLEX
            .def("_learn",&pyLearn_Inf<Cplex>)
            #endif
            #ifdef WITH_QPBO
            .def("_learn",&pyLearn_Inf<QpboExternal>)
            #endif
            #ifdef WITH_TRWS
            .def("_learn",&pyLearn_Inf<TrwsExternal>)
            #endif

            // REDUCED INFERENCE
            #ifdef WITH_QPBO
                .def("_learnReducedInf",&pyLearn_ReducedInf<LazyFlipperInf>)
                #ifdef WITH_TRWS
                .def("_learnReducedInf",&pyLearn_ReducedInf<TrwsExternal>)
                #endif
                #ifdef WITH_CPLEX
                .def("_learnReducedInf",&pyLearn_ReducedInf<Cplex>)
                #endif
            #endif

            // SELF FUSION
            #ifdef WITH_TRWS
            .def("_learnSelfFusion",&pyLearn_SelfFusion<TrwsExternal>)
            #endif

            // REDUCED INFERNCE SELF FUSION
            #if defined(WITH_TRWS) && defined(WITH_QPBO)
            .def("_learnReducedInfSelfFusion",&pyLearn_ReducedInfSelfFusion<TrwsExternal>)
            #endif
        ;
    }
};

template<class DS>
class DatasetInferenceSuite: public boost::python::def_visitor<DatasetInferenceSuite<DS> >{
public:
   friend class boost::python::def_visitor_access;

   DatasetInferenceSuite(){

   }

   template<class INF>
   static typename DS::ValueType pyGetLossWithInf(DS & ds, const typename INF::Parameter & param, const size_t i)
   {
       return ds. template getLoss<INF>(param, i);
   }

   template<class INF>
   static typename DS::ValueType pyGetTotalLossWithInf(DS & ds, const typename INF::Parameter & param)
   {
       return ds. template getTotalLoss<INF>(param);
   }

   template <class classT>
   void visit(classT& c) const{
       // SOME INFERENCE METHODS
       typedef typename DS::GMType GMType;
       typedef opengm::Minimizer ACC;

       typedef opengm::ICM<GMType, ACC> IcmInf;
       typedef opengm::LazyFlipper<GMType, ACC> LazyFlipperInf;
       typedef opengm::BeliefPropagationUpdateRules<GMType, ACC> UpdateRulesType;
       typedef opengm::MessagePassing<GMType, ACC, UpdateRulesType, opengm::MaxDistance> BpInf;

#ifdef WITH_CPLEX
       typedef opengm::LPCplex<GMType, ACC> Cplex;
#endif
#ifdef WITH_QPBO
       typedef opengm::external::QPBO<GMType>  QpboExternal;
#endif
#ifdef WITH_TRWS
       typedef opengm::external::TRWS<GMType>  TrwsExternal;
#endif

      c
          .def("_getLoss",&pyGetLossWithInf<IcmInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<IcmInf>)
          .def("_getLoss",&pyGetLossWithInf<LazyFlipperInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<LazyFlipperInf>)
          .def("_getLoss",&pyGetLossWithInf<BpInf>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<BpInf>)
#ifdef WITH_CPLEX
          .def("_getLoss",&pyGetLossWithInf<Cplex>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<Cplex>)
#endif
#ifdef WITH_QPBO
          .def("_getLoss",&pyGetLossWithInf<QpboExternal>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<QpboExternal>)
#endif
#ifdef WITH_TRWS
          .def("_getLoss",&pyGetLossWithInf<TrwsExternal>)
          .def("_getTotalLoss",&pyGetTotalLossWithInf<TrwsExternal>)
#endif
      ;
   }
};

} // namespace opengm

#endif // HELPER_HXX

<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/core/kernels/data/shard_dataset_op.h"

#include "tensorflow/core/framework/partial_tensor_shape.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/kernels/data/name_utils.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/platform/stringprintf.h"
#include "tensorflow/core/util/batch_util.h"

namespace tensorflow {
namespace data {

// See documentation in ../../ops/dataset_ops.cc for a high-level
// description of the following op.

/* static */ constexpr const char* const ShardDatasetOp::kDatasetType;
/* static */ constexpr const char* const ShardDatasetOp::kInputDataset;
/* static */ constexpr const char* const ShardDatasetOp::kNumShards;
/* static */ constexpr const char* const ShardDatasetOp::kIndex;
/* static */ constexpr const char* const ShardDatasetOp::kRequireNonEmpty;
/* static */ constexpr const char* const ShardDatasetOp::kOutputTypes;
/* static */ constexpr const char* const ShardDatasetOp::kOutputShapes;

constexpr char kInputImplEmpty[] = "input_impl_empty";
constexpr char kNextIndex[] = "next_index";

class ShardDatasetOp::Dataset : public DatasetBase {
 public:
  Dataset(OpKernelContext* ctx, int64 num_shards, int64 index,
          bool require_non_empty, const DatasetBase* input)
      : DatasetBase(DatasetContext(ctx)),
        num_shards_(num_shards),
        index_(index),
        input_(input),
        require_non_empty_(require_non_empty),
        traceme_metadata_(
            {{"index", strings::Printf("%lld", static_cast<long long>(index))},
             {"num_shards",
              strings::Printf("%lld", static_cast<long long>(num_shards))}}) {
    input_->Ref();
  }

  ~Dataset() override { input_->Unref(); }

  std::unique_ptr<IteratorBase> MakeIteratorInternal(
      const string& prefix) const override {
    return absl::make_unique<Iterator>(Iterator::Params{
        this, name_utils::IteratorPrefix(kDatasetType, prefix)});
  }

  const DataTypeVector& output_dtypes() const override {
    return input_->output_dtypes();
  }

  const std::vector<PartialTensorShape>& output_shapes() const override {
    return input_->output_shapes();
  }

  string DebugString() const override {
    name_utils::DatasetDebugStringParams params;
    params.set_args(num_shards_, index_);
    return name_utils::DatasetDebugString(kDatasetType, params);
  }

  int64 Cardinality() const override {
    int64 n = input_->Cardinality();
    if (n == kInfiniteCardinality || n == kUnknownCardinality) {
      return n;
    }
    return n / num_shards_ + (index_ < n % num_shards_ ? 1 : 0);
  }

  Status InputDatasets(std::vector<const DatasetBase*>* inputs) const override {
    inputs->push_back(input_);
    return Status::OK();
  }

  Status CheckExternalState() const override {
    return input_->CheckExternalState();
  }

 protected:
  Status AsGraphDefInternal(SerializationContext* ctx,
                            DatasetGraphDefBuilder* b,
                            Node** output) const override {
    Node* input_graph_node = nullptr;
    TF_RETURN_IF_ERROR(b->AddInputDataset(ctx, input_, &input_graph_node));
    Node* num_shards = nullptr;
    TF_RETURN_IF_ERROR(b->AddScalar(num_shards_, &num_shards));
    Node* index = nullptr;
    TF_RETURN_IF_ERROR(b->AddScalar(index_, &index));

    AttrValue require_non_empty_attr;
    b->BuildAttrValue(require_non_empty_, &require_non_empty_attr);

    TF_RETURN_IF_ERROR(
        b->AddDataset(this, {input_graph_node, num_shards, index},
                      {{kRequireNonEmpty, require_non_empty_attr}}, output));
    return Status::OK();
  }

 private:
  class Iterator : public DatasetIterator<Dataset> {
   public:
    explicit Iterator(const Params& params)
        : DatasetIterator<Dataset>(params), next_index_(0) {}

    Status Initialize(IteratorContext* ctx) override {
      return dataset()->input_->MakeIterator(ctx, this, prefix(), &input_impl_);
    }

    Status GetNextInternal(IteratorContext* ctx,
                           std::vector<Tensor>* out_tensors,
                           bool* end_of_sequence) override {
      mutex_lock l(mu_);

      *end_of_sequence = false;
      if (!input_impl_) {
        *end_of_sequence = true;
        return Status::OK();
      }

      int num_to_skip =
          (dataset()->index_ - next_index_) % dataset()->num_shards_;
      if (num_to_skip < 0) {
        num_to_skip += dataset()->num_shards_;
      }
      int num_skipped;
      TF_RETURN_IF_ERROR(
          input_impl_->Skip(ctx, num_to_skip, end_of_sequence, &num_skipped));
      next_index_ += num_skipped;
      if (*end_of_sequence) {
        input_impl_.reset();
        return Status::OK();
      }

      std::vector<Tensor> result;
      TF_RETURN_IF_ERROR(input_impl_->GetNext(ctx, &result, end_of_sequence));
      if (*end_of_sequence) {
        input_impl_.reset();
        return Status::OK();
      }
      next_index_++;

      if (dataset()->require_non_empty_ &&
          next_index_ < dataset()->num_shards_) {
        int num_skipped;
        Status s = input_impl_->Skip(ctx, dataset()->num_shards_ - next_index_,
                                     end_of_sequence, &num_skipped);
        if (*end_of_sequence || errors::IsOutOfRange(s)) {
          return errors::InvalidArgument(
              "There aren't enough elements in this dataset for each shard to "
              "have at least one element (# elems = ",
              next_index_, ", ", "# shards = ", dataset()->num_shards_,
              "). If you are using datasets with distribution strategy, "
              "considering setting the auto sharding policy to either DATA or "
              "OFF using the `experimental_distribute.auto_shard_policy` option"
              "of `tf.data.Options()`.");
        } else if (!s.ok()) {
          return s;
        }

        next_index_ = dataset()->num_shards_;
      }

      *out_tensors = std::move(result);
      return Status::OK();
    }

   protected:
    std::shared_ptr<model::Node> CreateNode(
        IteratorContext* ctx, model::Node::Args args) const override {
      return model::MakeKnownRatioNode(std::move(args), dataset()->num_shards_);
    }

    Status SaveInternal(SerializationContext* ctx,
                        IteratorStateWriter* writer) override {
      mutex_lock l(mu_);
      if (!input_impl_) {
        TF_RETURN_IF_ERROR(writer->WriteScalar(full_name(kInputImplEmpty), ""));
      } else {
        TF_RETURN_IF_ERROR(SaveInput(ctx, writer, input_impl_));
        TF_RETURN_IF_ERROR(
            writer->WriteScalar(full_name(kNextIndex), next_index_));
      }
      return Status::OK();
    }

    Status RestoreInternal(IteratorContext* ctx,
                           IteratorStateReader* reader) override {
      mutex_lock l(mu_);
      if (!reader->Contains(full_name(kInputImplEmpty))) {
        TF_RETURN_IF_ERROR(RestoreInput(ctx, reader, input_impl_));
        TF_RETURN_IF_ERROR(
            reader->ReadScalar(full_name(kNextIndex), &next_index_));
      } else {
        input_impl_.reset();
      }
      return Status::OK();
    }

    TraceMeMetadata GetTraceMeMetadata() const override {
      return dataset()->traceme_metadata_;
    }

   private:
    mutex mu_;
    std::unique_ptr<IteratorBase> input_impl_ TF_GUARDED_BY(mu_);
    int64 next_index_ TF_GUARDED_BY(mu_);
  };

  const int64 num_shards_;
  const int64 index_;
  const DatasetBase* const input_;
  const bool require_non_empty_;
  const TraceMeMetadata traceme_metadata_;
};

ShardDatasetOp::ShardDatasetOp(OpKernelConstruction* ctx)
    : UnaryDatasetOpKernel(ctx) {
  OP_REQUIRES_OK(ctx, ctx->GetAttr(kRequireNonEmpty, &require_non_empty_));
}

void ShardDatasetOp::MakeDataset(OpKernelContext* ctx, DatasetBase* input,
                                 DatasetBase** output) {
  int64 index = 0;
  int64 num_shards = 0;

  OP_REQUIRES_OK(ctx, ParseScalarArgument<int64>(ctx, kNumShards, &num_shards));
  OP_REQUIRES(
      ctx, num_shards > 0,
      errors::InvalidArgument("Number of shards must be greater than zero "
                              "(currently num_shards = ",
                              num_shards, ")."));

  OP_REQUIRES_OK(ctx, ParseScalarArgument<int64>(ctx, kIndex, &index));
  OP_REQUIRES(
      ctx, index >= 0 && index < num_shards,
      errors::InvalidArgument("Index must be between 0 and ", num_shards - 1,
                              " (currently index = ", index, ")."));

  *output = new Dataset(ctx, num_shards, index, require_non_empty_, input);
}

namespace {
REGISTER_KERNEL_BUILDER(Name("ShardDataset").Device(DEVICE_CPU),
                        ShardDatasetOp);
}  // namespace
}  // namespace data
}  // namespace tensorflow
<commit_msg>Improve error message when number of files is smaller than number of shards when trying to auto shard by FILE. Also improve documentation in the input guide along those lines.<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/core/kernels/data/shard_dataset_op.h"

#include "tensorflow/core/framework/partial_tensor_shape.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/kernels/data/name_utils.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/platform/stringprintf.h"
#include "tensorflow/core/util/batch_util.h"

namespace tensorflow {
namespace data {

// See documentation in ../../ops/dataset_ops.cc for a high-level
// description of the following op.

/* static */ constexpr const char* const ShardDatasetOp::kDatasetType;
/* static */ constexpr const char* const ShardDatasetOp::kInputDataset;
/* static */ constexpr const char* const ShardDatasetOp::kNumShards;
/* static */ constexpr const char* const ShardDatasetOp::kIndex;
/* static */ constexpr const char* const ShardDatasetOp::kRequireNonEmpty;
/* static */ constexpr const char* const ShardDatasetOp::kOutputTypes;
/* static */ constexpr const char* const ShardDatasetOp::kOutputShapes;

constexpr char kInputImplEmpty[] = "input_impl_empty";
constexpr char kNextIndex[] = "next_index";

class ShardDatasetOp::Dataset : public DatasetBase {
 public:
  Dataset(OpKernelContext* ctx, int64 num_shards, int64 index,
          bool require_non_empty, const DatasetBase* input)
      : DatasetBase(DatasetContext(ctx)),
        num_shards_(num_shards),
        index_(index),
        input_(input),
        require_non_empty_(require_non_empty),
        traceme_metadata_(
            {{"index", strings::Printf("%lld", static_cast<long long>(index))},
             {"num_shards",
              strings::Printf("%lld", static_cast<long long>(num_shards))}}) {
    input_->Ref();
  }

  ~Dataset() override { input_->Unref(); }

  std::unique_ptr<IteratorBase> MakeIteratorInternal(
      const string& prefix) const override {
    return absl::make_unique<Iterator>(Iterator::Params{
        this, name_utils::IteratorPrefix(kDatasetType, prefix)});
  }

  const DataTypeVector& output_dtypes() const override {
    return input_->output_dtypes();
  }

  const std::vector<PartialTensorShape>& output_shapes() const override {
    return input_->output_shapes();
  }

  string DebugString() const override {
    name_utils::DatasetDebugStringParams params;
    params.set_args(num_shards_, index_);
    return name_utils::DatasetDebugString(kDatasetType, params);
  }

  int64 Cardinality() const override {
    int64 n = input_->Cardinality();
    if (n == kInfiniteCardinality || n == kUnknownCardinality) {
      return n;
    }
    return n / num_shards_ + (index_ < n % num_shards_ ? 1 : 0);
  }

  Status InputDatasets(std::vector<const DatasetBase*>* inputs) const override {
    inputs->push_back(input_);
    return Status::OK();
  }

  Status CheckExternalState() const override {
    return input_->CheckExternalState();
  }

 protected:
  Status AsGraphDefInternal(SerializationContext* ctx,
                            DatasetGraphDefBuilder* b,
                            Node** output) const override {
    Node* input_graph_node = nullptr;
    TF_RETURN_IF_ERROR(b->AddInputDataset(ctx, input_, &input_graph_node));
    Node* num_shards = nullptr;
    TF_RETURN_IF_ERROR(b->AddScalar(num_shards_, &num_shards));
    Node* index = nullptr;
    TF_RETURN_IF_ERROR(b->AddScalar(index_, &index));

    AttrValue require_non_empty_attr;
    b->BuildAttrValue(require_non_empty_, &require_non_empty_attr);

    TF_RETURN_IF_ERROR(
        b->AddDataset(this, {input_graph_node, num_shards, index},
                      {{kRequireNonEmpty, require_non_empty_attr}}, output));
    return Status::OK();
  }

 private:
  class Iterator : public DatasetIterator<Dataset> {
   public:
    explicit Iterator(const Params& params)
        : DatasetIterator<Dataset>(params), next_index_(0) {}

    Status Initialize(IteratorContext* ctx) override {
      return dataset()->input_->MakeIterator(ctx, this, prefix(), &input_impl_);
    }

    Status GetNextInternal(IteratorContext* ctx,
                           std::vector<Tensor>* out_tensors,
                           bool* end_of_sequence) override {
      mutex_lock l(mu_);

      *end_of_sequence = false;
      if (!input_impl_) {
        *end_of_sequence = true;
        return Status::OK();
      }

      int num_to_skip =
          (dataset()->index_ - next_index_) % dataset()->num_shards_;
      if (num_to_skip < 0) {
        num_to_skip += dataset()->num_shards_;
      }
      int num_skipped;
      TF_RETURN_IF_ERROR(
          input_impl_->Skip(ctx, num_to_skip, end_of_sequence, &num_skipped));
      next_index_ += num_skipped;
      if (*end_of_sequence) {
        input_impl_.reset();
        return Status::OK();
      }

      std::vector<Tensor> result;
      TF_RETURN_IF_ERROR(input_impl_->GetNext(ctx, &result, end_of_sequence));
      if (*end_of_sequence) {
        input_impl_.reset();
        return Status::OK();
      }
      next_index_++;

      if (dataset()->require_non_empty_ &&
          next_index_ < dataset()->num_shards_) {
        int num_skipped;
        Status s = input_impl_->Skip(ctx, dataset()->num_shards_ - next_index_,
                                     end_of_sequence, &num_skipped);
        if (*end_of_sequence || errors::IsOutOfRange(s)) {
          // `dataset()->require_non_empty_` implies that this transformation
          // was introduced by auto_sharding rewrite, so it's acceptable
          // produce an error message that assumes auto-sharding context.
          return errors::InvalidArgument(
              "Could not apply FILE based sharding: the dataset only has ",
              next_index_, " file(s), which is not enough for the required ",
              dataset()->num_shards_,
              " shards/workers."
              "If you are using datasets with distribution strategy, "
              "consider setting the auto sharding policy to either DATA or "
              "OFF using the `experimental_distribute.auto_shard_policy` option"
              "of `tf.data.Options()`. Or, split your input files into a "
              "larger number of small files such that number of files is "
              "greater than number of shards/workers.");
        } else if (!s.ok()) {
          return s;
        }

        next_index_ = dataset()->num_shards_;
      }

      *out_tensors = std::move(result);
      return Status::OK();
    }

   protected:
    std::shared_ptr<model::Node> CreateNode(
        IteratorContext* ctx, model::Node::Args args) const override {
      return model::MakeKnownRatioNode(std::move(args), dataset()->num_shards_);
    }

    Status SaveInternal(SerializationContext* ctx,
                        IteratorStateWriter* writer) override {
      mutex_lock l(mu_);
      if (!input_impl_) {
        TF_RETURN_IF_ERROR(writer->WriteScalar(full_name(kInputImplEmpty), ""));
      } else {
        TF_RETURN_IF_ERROR(SaveInput(ctx, writer, input_impl_));
        TF_RETURN_IF_ERROR(
            writer->WriteScalar(full_name(kNextIndex), next_index_));
      }
      return Status::OK();
    }

    Status RestoreInternal(IteratorContext* ctx,
                           IteratorStateReader* reader) override {
      mutex_lock l(mu_);
      if (!reader->Contains(full_name(kInputImplEmpty))) {
        TF_RETURN_IF_ERROR(RestoreInput(ctx, reader, input_impl_));
        TF_RETURN_IF_ERROR(
            reader->ReadScalar(full_name(kNextIndex), &next_index_));
      } else {
        input_impl_.reset();
      }
      return Status::OK();
    }

    TraceMeMetadata GetTraceMeMetadata() const override {
      return dataset()->traceme_metadata_;
    }

   private:
    mutex mu_;
    std::unique_ptr<IteratorBase> input_impl_ TF_GUARDED_BY(mu_);
    int64 next_index_ TF_GUARDED_BY(mu_);
  };

  const int64 num_shards_;
  const int64 index_;
  const DatasetBase* const input_;
  const bool require_non_empty_;
  const TraceMeMetadata traceme_metadata_;
};

ShardDatasetOp::ShardDatasetOp(OpKernelConstruction* ctx)
    : UnaryDatasetOpKernel(ctx) {
  OP_REQUIRES_OK(ctx, ctx->GetAttr(kRequireNonEmpty, &require_non_empty_));
}

void ShardDatasetOp::MakeDataset(OpKernelContext* ctx, DatasetBase* input,
                                 DatasetBase** output) {
  int64 index = 0;
  int64 num_shards = 0;

  OP_REQUIRES_OK(ctx, ParseScalarArgument<int64>(ctx, kNumShards, &num_shards));
  OP_REQUIRES(
      ctx, num_shards > 0,
      errors::InvalidArgument("Number of shards must be greater than zero "
                              "(currently num_shards = ",
                              num_shards, ")."));

  OP_REQUIRES_OK(ctx, ParseScalarArgument<int64>(ctx, kIndex, &index));
  OP_REQUIRES(
      ctx, index >= 0 && index < num_shards,
      errors::InvalidArgument("Index must be between 0 and ", num_shards - 1,
                              " (currently index = ", index, ")."));

  *output = new Dataset(ctx, num_shards, index, require_non_empty_, input);
}

namespace {
REGISTER_KERNEL_BUILDER(Name("ShardDataset").Device(DEVICE_CPU),
                        ShardDatasetOp);
}  // namespace
}  // namespace data
}  // namespace tensorflow
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#ifdef INTEL_MKL

#define EIGEN_USE_THREADS

#include "dnnl.hpp"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/type_traits.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/graph/mkl_graph_util.h"
#include "tensorflow/core/kernels/meta_support.h"
#include "tensorflow/core/kernels/quantization_utils.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/util/mkl_util.h"

using dnnl::primitive_attr;
using dnnl::stream;

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;

template <typename Device, typename T, bool native_format = false>
class MklDequantizeOp : public OpKernel {
 public:
  explicit MklDequantizeOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
    string mode_string;
    OP_REQUIRES_OK(ctx, ctx->GetAttr("mode", &mode_string));
    OP_REQUIRES(ctx, mode_string == "SCALED",
                errors::InvalidArgument(
                    "MklDequantizeOp only supports 'SCALED' mode, but got '" +
                    mode_string + "'"));

    OP_REQUIRES_OK(ctx, ctx->GetAttr("narrow_range", &narrow_range_));
  }

  void Compute(OpKernelContext* ctx) override {
    try {
      // Using CPU device
      auto cpu_engine = engine(engine::kind::cpu, 0);

      // Get the inputs
      const Tensor& src_tensor = ctx->input(kSrcIndex);
      const float min_range = ctx->input(kMinIndex).flat<float>()(0);
      const float max_range = ctx->input(kMaxIndex).flat<float>()(0);

      // Get MklShape
      auto src_tf_shape = src_tensor.shape();

      // src_dims is the dimension of src_tensor
      // output_dims are same as src_dims
      auto src_dims = TFShapeToMklDnnDims(src_tensor.shape());
      auto output_dims = src_dims;

      // Create reorder memory for src and dst
      MklDnnData<T> src(&cpu_engine);
      MklDnnData<float> dst(&cpu_engine);

      std::shared_ptr<stream> reorder_stream;
      MklDnnThreadPool eigen_tp(ctx);
      reorder_stream.reset(CreateStream(&eigen_tp, cpu_engine));

      memory::format_tag dst_layout_type;
      switch (src_tf_shape.dims()) {
        case 1:
          dst_layout_type = memory::format_tag::x;
          break;
        case 2:
          dst_layout_type = memory::format_tag::nc;
          break;
        case 3:
          dst_layout_type = memory::format_tag::tnc;
          break;
        case 4:
          dst_layout_type = memory::format_tag::nhwc;
          break;
        case 5:
          dst_layout_type = memory::format_tag::ndhwc;
          break;
        default:
          OP_REQUIRES_OK(
              ctx, errors::InvalidArgument("Input dims must be <= 5 and >= 1"));
          return;
      }

      // If input is in MKL layout, then simply grab input layout; otherwise,
      // construct input TF layout. For TF layout, although input shape
      // (src_dims) required is in MKL-DNN order, the layout is Tensorflow's
      // layout
      auto src_md = memory::desc(src_dims, MklDnnType<T>(), dst_layout_type);

      src.SetUsrMem(src_md, &src_tensor);
      src.SetUsrMemDataHandle(&src_tensor, reorder_stream);

      Tensor* output_tensor = nullptr;
      MklDnnShape output_mkl_shape;
      TensorShape output_tf_shape;
      memory::desc dst_md =
          memory::desc(src_dims, MklDnnType<float>(), dst_layout_type);

      // If input is MKL shape, output is also MKL shape.
      // If input is TF shape, output is also TF shape.
      output_mkl_shape.SetMklTensor(false);
      output_tf_shape = MklDnnDimsToTFShape(output_dims);

      // Allocate MKL or TF output shape based on the above
      AllocateOutputSetMklShape(ctx, 0, &output_tensor, output_tf_shape,
                                output_mkl_shape, native_format);
      dst.SetUsrMem(dst_md, output_tensor);
      dst.SetUsrMemDataHandle(output_tensor, reorder_stream);

      // The quantization logic here for mode SCALED is similar to the logic
      // in QuantizeAndDequantizeV2 and QuantizeAndDequantizeV3.
      static constexpr int num_bits = sizeof(T) * 8;
      const float max_abs = std::max(std::abs(min_range), std::abs(max_range));
      bool is_signed = std::is_signed<T>::value;

      const int target_bits = is_signed ? (num_bits - 1) : num_bits;
      const float v_max = static_cast<float>(uint64_t{1} << target_bits) - 1;
      float v_min = 0;
      if (is_signed) {
        v_min = -(static_cast<float>(uint64_t{1} << target_bits));
      }
      if (narrow_range_) {
        v_min += 1;
      }
      float scale_factor;
      if (v_min != 0) {
        scale_factor = std::max(min_range / v_min, max_range / v_max);
      } else {
        scale_factor = max_range / v_max;
      }
      std::vector<float> scales;
      scales.push_back(scale_factor);
      primitive_attr attr;
      attr.set_output_scales(0, scales);
      std::vector<primitive> net;

      // Create reorder primitive and then execute.
      auto reorder_pd =
          ReorderPd(cpu_engine, src.GetUsrMem()->get_desc(), cpu_engine,
                    dst.GetUsrMem()->get_desc(), attr);
      net.push_back(reorder(reorder_pd));
      std::vector<std::unordered_map<int, memory>> reorder_net_args;
      reorder_net_args.push_back(
          {{DNNL_ARG_FROM, *src.GetUsrMem()}, {DNNL_ARG_TO, *dst.GetUsrMem()}});
      execute_primitives(net, reorder_stream, reorder_net_args);
    } catch (dnnl::error& e) {
      string error_msg = "Status: " + std::to_string(e.status) +
                         ", message: " + string(e.message) + ", in file " +
                         string(__FILE__) + ":" + std::to_string(__LINE__);
      OP_REQUIRES_OK(
          ctx, errors::Aborted("Operation received an exception:", error_msg));
    }
  }

 private:
  const size_t kSrcIndex = 0;
  const size_t kMinIndex = 1;
  const size_t kMaxIndex = 2;
  bool narrow_range_;
};

REGISTER_KERNEL_BUILDER(Name("_MklDequantize")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<quint8>("T")
                            .Label(mkl_op_registry::kMklQuantizedOpLabel),
                        MklDequantizeOp<CPUDevice, quint8, true>);
REGISTER_KERNEL_BUILDER(Name("_MklDequantize")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<qint8>("T")
                            .Label(mkl_op_registry::kMklQuantizedOpLabel),
                        MklDequantizeOp<CPUDevice, qint8, true>);

}  // namespace tensorflow

#endif  // INTEL_MKL
<commit_msg>Fix compilation error from PR #56086, reported in https://github.com/tensorflow/tensorflow/pull/56086#issuecomment-1196063686<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#ifdef INTEL_MKL

#define EIGEN_USE_THREADS

#include "dnnl.hpp"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/type_traits.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/graph/mkl_graph_util.h"
#include "tensorflow/core/kernels/meta_support.h"
#include "tensorflow/core/kernels/quantization_utils.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/util/mkl_util.h"

using dnnl::primitive_attr;
using dnnl::stream;

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;

template <typename Device, typename T, bool native_format = false>
class MklDequantizeOp : public OpKernel {
 public:
  explicit MklDequantizeOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
    string mode_string;
    OP_REQUIRES_OK(ctx, ctx->GetAttr("mode", &mode_string));
    OP_REQUIRES(ctx, mode_string == "SCALED",
                errors::InvalidArgument(
                    "MklDequantizeOp only supports 'SCALED' mode, but got '" +
                    mode_string + "'"));

    OP_REQUIRES_OK(ctx, ctx->GetAttr("narrow_range", &narrow_range_));
  }

  void Compute(OpKernelContext* ctx) override {
    try {
      // Using CPU device
      auto cpu_engine = engine(engine::kind::cpu, 0);

      // Get the inputs
      const Tensor& src_tensor = ctx->input(kSrcIndex);
      const float min_range = ctx->input(kMinIndex).template flat<float>()(0);
      const float max_range = ctx->input(kMaxIndex).template flat<float>()(0);

      // Get MklShape
      auto src_tf_shape = src_tensor.shape();

      // src_dims is the dimension of src_tensor
      // output_dims are same as src_dims
      auto src_dims = TFShapeToMklDnnDims(src_tensor.shape());
      auto output_dims = src_dims;

      // Create reorder memory for src and dst
      MklDnnData<T> src(&cpu_engine);
      MklDnnData<float> dst(&cpu_engine);

      std::shared_ptr<stream> reorder_stream;
      MklDnnThreadPool eigen_tp(ctx);
      reorder_stream.reset(CreateStream(&eigen_tp, cpu_engine));

      memory::format_tag dst_layout_type;
      switch (src_tf_shape.dims()) {
        case 1:
          dst_layout_type = memory::format_tag::x;
          break;
        case 2:
          dst_layout_type = memory::format_tag::nc;
          break;
        case 3:
          dst_layout_type = memory::format_tag::tnc;
          break;
        case 4:
          dst_layout_type = memory::format_tag::nhwc;
          break;
        case 5:
          dst_layout_type = memory::format_tag::ndhwc;
          break;
        default:
          OP_REQUIRES_OK(
              ctx, errors::InvalidArgument("Input dims must be <= 5 and >= 1"));
          return;
      }

      // If input is in MKL layout, then simply grab input layout; otherwise,
      // construct input TF layout. For TF layout, although input shape
      // (src_dims) required is in MKL-DNN order, the layout is Tensorflow's
      // layout
      auto src_md = memory::desc(src_dims, MklDnnType<T>(), dst_layout_type);

      src.SetUsrMem(src_md, &src_tensor);
      src.SetUsrMemDataHandle(&src_tensor, reorder_stream);

      Tensor* output_tensor = nullptr;
      MklDnnShape output_mkl_shape;
      TensorShape output_tf_shape;
      memory::desc dst_md =
          memory::desc(src_dims, MklDnnType<float>(), dst_layout_type);

      // If input is MKL shape, output is also MKL shape.
      // If input is TF shape, output is also TF shape.
      output_mkl_shape.SetMklTensor(false);
      output_tf_shape = MklDnnDimsToTFShape(output_dims);

      // Allocate MKL or TF output shape based on the above
      AllocateOutputSetMklShape(ctx, 0, &output_tensor, output_tf_shape,
                                output_mkl_shape, native_format);
      dst.SetUsrMem(dst_md, output_tensor);
      dst.SetUsrMemDataHandle(output_tensor, reorder_stream);

      // The quantization logic here for mode SCALED is similar to the logic
      // in QuantizeAndDequantizeV2 and QuantizeAndDequantizeV3.
      static constexpr int num_bits = sizeof(T) * 8;
      const float max_abs = std::max(std::abs(min_range), std::abs(max_range));
      bool is_signed = std::is_signed<T>::value;

      const int target_bits = is_signed ? (num_bits - 1) : num_bits;
      const float v_max = static_cast<float>(uint64_t{1} << target_bits) - 1;
      float v_min = 0;
      if (is_signed) {
        v_min = -(static_cast<float>(uint64_t{1} << target_bits));
      }
      if (narrow_range_) {
        v_min += 1;
      }
      float scale_factor;
      if (v_min != 0) {
        scale_factor = std::max(min_range / v_min, max_range / v_max);
      } else {
        scale_factor = max_range / v_max;
      }
      std::vector<float> scales;
      scales.push_back(scale_factor);
      primitive_attr attr;
      attr.set_output_scales(0, scales);
      std::vector<primitive> net;

      // Create reorder primitive and then execute.
      auto reorder_pd =
          ReorderPd(cpu_engine, src.GetUsrMem()->get_desc(), cpu_engine,
                    dst.GetUsrMem()->get_desc(), attr);
      net.push_back(reorder(reorder_pd));
      std::vector<std::unordered_map<int, memory>> reorder_net_args;
      reorder_net_args.push_back(
          {{DNNL_ARG_FROM, *src.GetUsrMem()}, {DNNL_ARG_TO, *dst.GetUsrMem()}});
      execute_primitives(net, reorder_stream, reorder_net_args);
    } catch (dnnl::error& e) {
      string error_msg = "Status: " + std::to_string(e.status) +
                         ", message: " + string(e.message) + ", in file " +
                         string(__FILE__) + ":" + std::to_string(__LINE__);
      OP_REQUIRES_OK(
          ctx, errors::Aborted("Operation received an exception:", error_msg));
    }
  }

 private:
  const size_t kSrcIndex = 0;
  const size_t kMinIndex = 1;
  const size_t kMaxIndex = 2;
  bool narrow_range_;
};

REGISTER_KERNEL_BUILDER(Name("_MklDequantize")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<quint8>("T")
                            .Label(mkl_op_registry::kMklQuantizedOpLabel),
                        MklDequantizeOp<CPUDevice, quint8, true>);
REGISTER_KERNEL_BUILDER(Name("_MklDequantize")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<qint8>("T")
                            .Label(mkl_op_registry::kMklQuantizedOpLabel),
                        MklDequantizeOp<CPUDevice, qint8, true>);

}  // namespace tensorflow

#endif  // INTEL_MKL
<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/cl/kernels/mean.h"

#include <string>

#include "tensorflow/lite/delegates/gpu/cl/kernels/util.h"
#include "tensorflow/lite/delegates/gpu/cl/kernels/work_group_picking.h"
#include "tensorflow/lite/delegates/gpu/common/status.h"
#include "tensorflow/lite/delegates/gpu/common/util.h"

namespace tflite {
namespace gpu {
namespace cl {
namespace {

std::string GetMeanKernelCode(
    const OperationDef& op_def,
    const std::vector<ElementwiseOperation*>& linked_operations,
    const int3& work_group_size) {
  TensorCodeGenerator src_tensor(
      "src_data", WHSPoint{"src_size.x", "src_size.y", "src_size.z"},
      op_def.src_tensors[0]);
  TensorCodeGenerator dst_tensor("dst_data", WHSPoint{"1", "1", "src_size.z"},
                                 op_def.dst_tensors[0]);

  std::string c = GetCommonDefines(op_def.precision);
  const std::string wg_x = std::to_string(work_group_size.x);
  const std::string wg_y = std::to_string(work_group_size.y);
  c += "__kernel void main_function(\n";
  c += src_tensor.GetDeclaration(AccessType::READ);
  c += GetArgsDeclaration(linked_operations);
  c += dst_tensor.GetDeclaration(AccessType::WRITE) + ",\n";
  c += "    int4 src_size,           \n";
  c += "    float2 inv_multipliers   \n";
  c += ") {\n";
  c += "  __local float4 accum[" +
       std::to_string(work_group_size.x * work_group_size.y) + "];\n";
  c += "  int local_x = get_local_id(0);\n";
  c += "  int local_y = get_local_id(1);\n";
  c += "  int local_id = local_y * " + wg_x + " + local_x;\n";
  c += "  int S = get_global_id(2);\n";
  c += "  if (S >= src_size.z) return;\n";
  c += "  accum[local_id] = (float4)(0.0f);\n";
  c += "  for (int s_y = local_y; s_y < src_size.y; s_y += " + wg_y + ") {\n";
  c += "    for (int s_x = local_x; s_x < src_size.x; s_x += " + wg_x + ") {\n";
  c += "        accum[local_id] += " +
       src_tensor.ReadAsFloatWHS("s_x", "s_y", "S") + ";\n";
  c += "    }\n";
  c += "  }\n";
  c += "  accum[local_id] *= inv_multipliers.x;\n";
  c += "  barrier(CLK_LOCAL_MEM_FENCE);\n";
  const int total_size = work_group_size.x * work_group_size.y;
  int offset = 1;
  int reminder = total_size / 4;
  for (; reminder >= 8; reminder /= 4, offset *= 4) {
    c += "  if (local_id < " + std::to_string(reminder) + ") {\n";
    c += "    int t = local_id * " + std::to_string(offset * 4) + ";\n";
    c += "    float4 sum = accum[t + " + std::to_string(offset) + "];\n";
    c += "    sum += accum[t + " + std::to_string(offset * 2) + "];\n";
    c += "    sum += accum[t + " + std::to_string(offset * 3) + "];\n";
    c += "    accum[t] += sum;\n";
    c += "  }\n";
    c += "  barrier(CLK_LOCAL_MEM_FENCE);\n";
  }
  c += "  float4 sum = accum[0];\n";
  reminder *= 4;
  for (int i = 1; i < reminder; ++i) {
    c += "  sum += accum[" + std::to_string(offset * i) + "];\n";
  }
  c += "  FLT4 result = TO_FLT4(sum * inv_multipliers.y);\n";
  c += PostProcess(linked_operations, {"result", "0", "0", "S"});
  c += "  " + dst_tensor.WriteWHS("result", "0", "0", "S");
  c += "}\n";
  return c;
}
}  // namespace

Mean::Mean(Mean&& operation)
    : GPUOperation(std::move(operation)),
      kernel_(std::move(operation.kernel_)),
      work_group_size_(operation.work_group_size_) {}

Mean& Mean::operator=(Mean&& operation) {
  if (this != &operation) {
    kernel_ = std::move(operation.kernel_);
    std::swap(work_group_size_, operation.work_group_size_);
    GPUOperation::operator=(std::move(operation));
  }
  return *this;
}

Status Mean::Compile(const CreationContext& creation_context) {
  const auto code =
      GetMeanKernelCode(definition_, linked_operations_, work_group_size_);
  return creation_context.cache->GetOrCreateCLKernel(
      code, "main_function", *creation_context.context,
      *creation_context.device, &kernel_);
}

Status Mean::BindArguments() {
  kernel_.ResetBindingCounter();
  RETURN_IF_ERROR(kernel_.SetMemoryAuto(src_[0]->GetMemoryPtr()));
  RETURN_IF_ERROR(BindArgs(&kernel_, linked_operations_));
  RETURN_IF_ERROR(kernel_.SetMemoryAuto(dst_[0]->GetMemoryPtrForWriting()));
  RETURN_IF_ERROR(kernel_.SetBytesAuto(src_[0]->GetWBatchedHSB()));
  const double total_size = src_[0]->Width() * src_[0]->Height();
  const double size_0 = work_group_size_.x * work_group_size_.y;
  const double size_1 = total_size / size_0;
  RETURN_IF_ERROR(kernel_.SetBytesAuto(float2(1.0 / size_1, 1.0 / size_0)));
  return OkStatus();
}

int3 Mean::GetGridSize() const {
  const int grid_x = work_group_size_.x * dst_[0]->Batch();
  const int grid_y = work_group_size_.y;
  const int grid_z = dst_[0]->Slices();
  return int3(grid_x, grid_y, grid_z);
}

Status Mean::AddToQueue(CLCommandQueue* queue) {
  RETURN_IF_ERROR(BindArguments());
  return queue->DispatchImplicit(kernel_, GetGridSize(), work_group_size_);
}

Mean CreateMean(const OperationDef& definition) { return Mean(definition); }

}  // namespace cl
}  // namespace gpu
}  // namespace tflite
<commit_msg>Fixed mean work group size for Adreno3xx.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/cl/kernels/mean.h"

#include <string>

#include "tensorflow/lite/delegates/gpu/cl/kernels/util.h"
#include "tensorflow/lite/delegates/gpu/cl/kernels/work_group_picking.h"
#include "tensorflow/lite/delegates/gpu/common/status.h"
#include "tensorflow/lite/delegates/gpu/common/util.h"

namespace tflite {
namespace gpu {
namespace cl {
namespace {

std::string GetMeanKernelCode(
    const OperationDef& op_def,
    const std::vector<ElementwiseOperation*>& linked_operations,
    const int3& work_group_size) {
  TensorCodeGenerator src_tensor(
      "src_data", WHSPoint{"src_size.x", "src_size.y", "src_size.z"},
      op_def.src_tensors[0]);
  TensorCodeGenerator dst_tensor("dst_data", WHSPoint{"1", "1", "src_size.z"},
                                 op_def.dst_tensors[0]);

  std::string c = GetCommonDefines(op_def.precision);
  const std::string wg_x = std::to_string(work_group_size.x);
  const std::string wg_y = std::to_string(work_group_size.y);
  c += "__kernel void main_function(\n";
  c += src_tensor.GetDeclaration(AccessType::READ);
  c += GetArgsDeclaration(linked_operations);
  c += dst_tensor.GetDeclaration(AccessType::WRITE) + ",\n";
  c += "    int4 src_size,           \n";
  c += "    float2 inv_multipliers   \n";
  c += ") {\n";
  c += "  __local float4 accum[" +
       std::to_string(work_group_size.x * work_group_size.y) + "];\n";
  c += "  int local_x = get_local_id(0);\n";
  c += "  int local_y = get_local_id(1);\n";
  c += "  int local_id = local_y * " + wg_x + " + local_x;\n";
  c += "  int S = get_global_id(2);\n";
  c += "  if (S >= src_size.z) return;\n";
  c += "  accum[local_id] = (float4)(0.0f);\n";
  c += "  for (int s_y = local_y; s_y < src_size.y; s_y += " + wg_y + ") {\n";
  c += "    for (int s_x = local_x; s_x < src_size.x; s_x += " + wg_x + ") {\n";
  c += "        accum[local_id] += " +
       src_tensor.ReadAsFloatWHS("s_x", "s_y", "S") + ";\n";
  c += "    }\n";
  c += "  }\n";
  c += "  accum[local_id] *= inv_multipliers.x;\n";
  c += "  barrier(CLK_LOCAL_MEM_FENCE);\n";
  const int total_size = work_group_size.x * work_group_size.y;
  int offset = 1;
  int reminder = total_size / 4;
  for (; reminder >= 8; reminder /= 4, offset *= 4) {
    c += "  if (local_id < " + std::to_string(reminder) + ") {\n";
    c += "    int t = local_id * " + std::to_string(offset * 4) + ";\n";
    c += "    float4 sum = accum[t + " + std::to_string(offset) + "];\n";
    c += "    sum += accum[t + " + std::to_string(offset * 2) + "];\n";
    c += "    sum += accum[t + " + std::to_string(offset * 3) + "];\n";
    c += "    accum[t] += sum;\n";
    c += "  }\n";
    c += "  barrier(CLK_LOCAL_MEM_FENCE);\n";
  }
  c += "  float4 sum = accum[0];\n";
  reminder *= 4;
  for (int i = 1; i < reminder; ++i) {
    c += "  sum += accum[" + std::to_string(offset * i) + "];\n";
  }
  c += "  FLT4 result = TO_FLT4(sum * inv_multipliers.y);\n";
  c += PostProcess(linked_operations, {"result", "0", "0", "S"});
  c += "  " + dst_tensor.WriteWHS("result", "0", "0", "S");
  c += "}\n";
  return c;
}
}  // namespace

Mean::Mean(Mean&& operation)
    : GPUOperation(std::move(operation)),
      kernel_(std::move(operation.kernel_)),
      work_group_size_(operation.work_group_size_) {}

Mean& Mean::operator=(Mean&& operation) {
  if (this != &operation) {
    kernel_ = std::move(operation.kernel_);
    std::swap(work_group_size_, operation.work_group_size_);
    GPUOperation::operator=(std::move(operation));
  }
  return *this;
}

Status Mean::Compile(const CreationContext& creation_context) {
  if (creation_context.device->IsAdreno3xx()) {
    work_group_size_ = int3(16, 8, 1);
  }
  const auto code =
      GetMeanKernelCode(definition_, linked_operations_, work_group_size_);
  return creation_context.cache->GetOrCreateCLKernel(
      code, "main_function", *creation_context.context,
      *creation_context.device, &kernel_);
}

Status Mean::BindArguments() {
  kernel_.ResetBindingCounter();
  RETURN_IF_ERROR(kernel_.SetMemoryAuto(src_[0]->GetMemoryPtr()));
  RETURN_IF_ERROR(BindArgs(&kernel_, linked_operations_));
  RETURN_IF_ERROR(kernel_.SetMemoryAuto(dst_[0]->GetMemoryPtrForWriting()));
  RETURN_IF_ERROR(kernel_.SetBytesAuto(src_[0]->GetWBatchedHSB()));
  const double total_size = src_[0]->Width() * src_[0]->Height();
  const double size_0 = work_group_size_.x * work_group_size_.y;
  const double size_1 = total_size / size_0;
  RETURN_IF_ERROR(kernel_.SetBytesAuto(float2(1.0 / size_1, 1.0 / size_0)));
  return OkStatus();
}

int3 Mean::GetGridSize() const {
  const int grid_x = work_group_size_.x * dst_[0]->Batch();
  const int grid_y = work_group_size_.y;
  const int grid_z = dst_[0]->Slices();
  return int3(grid_x, grid_y, grid_z);
}

Status Mean::AddToQueue(CLCommandQueue* queue) {
  RETURN_IF_ERROR(BindArguments());
  return queue->DispatchImplicit(kernel_, GetGridSize(), work_group_size_);
}

Mean CreateMean(const OperationDef& definition) { return Mean(definition); }

}  // namespace cl
}  // namespace gpu
}  // namespace tflite
<|endoftext|>


<commit_before>/*
 * MIT License
 *
 * Copyright (c) 2016 xiongziliang <771730766@qq.com>
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <string.h>
#include "strCoding.h"

#if defined(_WIN32)
#include <windows.h>
#endif//defined(_WIN32)

namespace ZL {
namespace Http {

//////////////////////////通用///////////////////////
void UTF8ToUnicode(WCHAR* pOut, const char *pText)
{
	char* uchar = (char *)pOut;
	uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
	uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);
	return;
}
void UnicodeToUTF8(char* pOut, const WCHAR* pText)
{
	// 注意 WCHAR高低字的顺序,低字节在前，高字节在后
	const char* pchar = (const char *)pText;
	pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
	pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
	pOut[2] = (0x80 | (pchar[0] & 0x3F));
	return;
}

char CharToInt(char ch)
{
	if (ch >= '0' && ch <= '9')return (char)(ch - '0');
	if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
	if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
	return -1;
}
char StrToBin(const char *str)
{
	char tempWord[2];
	char chn;
	tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011
	tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000
	chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000
	return chn;
}

string strCoding::UrlUTF8Encode(const string &str) {
	string dd;
	size_t len = str.size();
	for (size_t i = 0; i < len; i++) {
		if (isalnum((uint8_t)str[i])) {
			char tempbuff[2];
			sprintf(tempbuff, "%c", str[i]);
			dd.append(tempbuff);
		}
		else if (isspace((uint8_t)str[i])) {
			dd.append("+");
		}
		else {
			char tempbuff[4];
			sprintf(tempbuff, "%%%X%X", (uint8_t)str[i] >> 4,(uint8_t)str[i] % 16);
			dd.append(tempbuff);
		}
	}
	return dd;
}
string strCoding::UrlUTF8Decode(const string &str) {
	string output = "";
	char tmp[2];
	int i = 0, len = str.length();
	while (i < len) {
		if (str[i] == '%') {
			tmp[0] = str[i + 1];
			tmp[1] = str[i + 2];
			output += StrToBin(tmp);
			i = i + 3;
		}
		else if (str[i] == '+') {
			output += ' ';
			i++;
		}
		else {
			output += str[i];
			i++;
		}
	}
	return output;
}

string strCoding::UrlGB2312Encode(const string &str)
{
	string dd;
	size_t len = str.size();
	for (size_t i = 0; i<len; i++)
	{
		if (isalnum((uint8_t)str[i]))
		{
			char tempbuff[2];
			sprintf(tempbuff, "%c", str[i]);
			dd.append(tempbuff);
		}
		else if (isspace((uint8_t)str[i]))
		{
			dd.append("+");
		}
		else
		{
			char tempbuff[4];
			sprintf(tempbuff, "%%%X%X", (uint8_t)str[i] >> 4, (uint8_t)str[i] % 16);
			dd.append(tempbuff);
		}
	}
	return dd;
}

string strCoding::UrlGB2312Decode(const string &str)
{
	string output = "";
	char tmp[2];
	int i = 0, idx = 0, len = str.length();
	while (i<len) {
		if (str[i] == '%') {
			tmp[0] = str[i + 1];
			tmp[1] = str[i + 2];
			output += StrToBin(tmp);
			i = i + 3;
		}
		else if (str[i] == '+') {
			output += ' ';
			i++;
		}
		else {
			output += str[i];
			i++;
		}
	}
	return output;
}

///////////////////////////////windows专用///////////////////////////////////
#if defined(_WIN32)
void UnicodeToGB2312(char* pOut, wchar_t uData)
{
	WideCharToMultiByte(CP_ACP, NULL, &uData, 1, pOut, sizeof(wchar_t), NULL, NULL);
}
void Gb2312ToUnicode(wchar_t* pOut, const char *gbBuffer)
{
	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, gbBuffer, 2, pOut, 1);
}

string strCoding::UTF8ToGB2312(const string &str) {
	auto len = str.size();
	auto pText = str.data();
	char Ctemp[4] = {0};
	char *pOut = new char[len + 1];
	memset(pOut, 0, len + 1);

	int i = 0, j = 0;
	while (i < len)
	{
		if (pText[i] >= 0)
		{
			pOut[j++] = pText[i++];
		}
		else
		{
			wchar_t Wtemp;
			UTF8ToUnicode(&Wtemp, pText + i);
			UnicodeToGB2312(Ctemp, Wtemp);
			pOut[j] = Ctemp[0];
			pOut[j + 1] = Ctemp[1];
			i += 3;
			j += 2;
		}
	}
	string ret = pOut;
	delete[] pOut;
	return ret;
}

string strCoding::GB2312ToUTF8(const string &str) {
	auto len = str.size();
	auto pText = str.data();
	char buf[4] = { 0 };
	int nLength = len * 3;
	char* pOut = new char[nLength];
	memset(pOut, 0, nLength);
	int i = 0, j = 0;
	while (i < len)
	{
		//如果是英文直接复制就可以
		if (*(pText + i) >= 0)
		{
			pOut[j++] = pText[i++];
		}
		else
		{
			wchar_t pbuffer;
			Gb2312ToUnicode(&pbuffer, pText + i);
			UnicodeToUTF8(buf, &pbuffer);
			pOut[j] = buf[0];
			pOut[j + 1] = buf[1];
			pOut[j + 2] = buf[2];
			j += 3;
			i += 2;
		}
	}
	string ret = pOut;
	delete[] pOut;
	return ret;
}
#endif//defined(_WIN32)

} /* namespace Http */
} /* namespace ZL */
<commit_msg>fixed<commit_after>/*
 * MIT License
 *
 * Copyright (c) 2016 xiongziliang <771730766@qq.com>
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <string.h>
#include "strCoding.h"

#if defined(_WIN32)
#include <windows.h>
#endif//defined(_WIN32)

namespace ZL {
namespace Http {

//////////////////////////通用///////////////////////
void UTF8ToUnicode(wchar_t* pOut, const char *pText)
{
	char* uchar = (char *)pOut;
	uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
	uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);
	return;
}
void UnicodeToUTF8(char* pOut, const wchar_t* pText)
{
	// 注意 WCHAR高低字的顺序,低字节在前，高字节在后
	const char* pchar = (const char *)pText;
	pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
	pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
	pOut[2] = (0x80 | (pchar[0] & 0x3F));
	return;
}

char CharToInt(char ch)
{
	if (ch >= '0' && ch <= '9')return (char)(ch - '0');
	if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
	if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
	return -1;
}
char StrToBin(const char *str)
{
	char tempWord[2];
	char chn;
	tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011
	tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000
	chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000
	return chn;
}

string strCoding::UrlUTF8Encode(const string &str) {
	string dd;
	size_t len = str.size();
	for (size_t i = 0; i < len; i++) {
		if (isalnum((uint8_t)str[i])) {
			char tempbuff[2];
			sprintf(tempbuff, "%c", str[i]);
			dd.append(tempbuff);
		}
		else if (isspace((uint8_t)str[i])) {
			dd.append("+");
		}
		else {
			char tempbuff[4];
			sprintf(tempbuff, "%%%X%X", (uint8_t)str[i] >> 4,(uint8_t)str[i] % 16);
			dd.append(tempbuff);
		}
	}
	return dd;
}
string strCoding::UrlUTF8Decode(const string &str) {
	string output = "";
	char tmp[2];
	int i = 0, len = str.length();
	while (i < len) {
		if (str[i] == '%') {
			tmp[0] = str[i + 1];
			tmp[1] = str[i + 2];
			output += StrToBin(tmp);
			i = i + 3;
		}
		else if (str[i] == '+') {
			output += ' ';
			i++;
		}
		else {
			output += str[i];
			i++;
		}
	}
	return output;
}

string strCoding::UrlGB2312Encode(const string &str)
{
	string dd;
	size_t len = str.size();
	for (size_t i = 0; i<len; i++)
	{
		if (isalnum((uint8_t)str[i]))
		{
			char tempbuff[2];
			sprintf(tempbuff, "%c", str[i]);
			dd.append(tempbuff);
		}
		else if (isspace((uint8_t)str[i]))
		{
			dd.append("+");
		}
		else
		{
			char tempbuff[4];
			sprintf(tempbuff, "%%%X%X", (uint8_t)str[i] >> 4, (uint8_t)str[i] % 16);
			dd.append(tempbuff);
		}
	}
	return dd;
}

string strCoding::UrlGB2312Decode(const string &str)
{
	string output = "";
	char tmp[2];
	int i = 0, idx = 0, len = str.length();
	while (i<len) {
		if (str[i] == '%') {
			tmp[0] = str[i + 1];
			tmp[1] = str[i + 2];
			output += StrToBin(tmp);
			i = i + 3;
		}
		else if (str[i] == '+') {
			output += ' ';
			i++;
		}
		else {
			output += str[i];
			i++;
		}
	}
	return output;
}

///////////////////////////////windows专用///////////////////////////////////
#if defined(_WIN32)
void UnicodeToGB2312(char* pOut, wchar_t uData)
{
	WideCharToMultiByte(CP_ACP, NULL, &uData, 1, pOut, sizeof(wchar_t), NULL, NULL);
}
void Gb2312ToUnicode(wchar_t* pOut, const char *gbBuffer)
{
	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, gbBuffer, 2, pOut, 1);
}

string strCoding::UTF8ToGB2312(const string &str) {
	auto len = str.size();
	auto pText = str.data();
	char Ctemp[4] = {0};
	char *pOut = new char[len + 1];
	memset(pOut, 0, len + 1);

	int i = 0, j = 0;
	while (i < len)
	{
		if (pText[i] >= 0)
		{
			pOut[j++] = pText[i++];
		}
		else
		{
			wchar_t Wtemp;
			UTF8ToUnicode(&Wtemp, pText + i);
			UnicodeToGB2312(Ctemp, Wtemp);
			pOut[j] = Ctemp[0];
			pOut[j + 1] = Ctemp[1];
			i += 3;
			j += 2;
		}
	}
	string ret = pOut;
	delete[] pOut;
	return ret;
}

string strCoding::GB2312ToUTF8(const string &str) {
	auto len = str.size();
	auto pText = str.data();
	char buf[4] = { 0 };
	int nLength = len * 3;
	char* pOut = new char[nLength];
	memset(pOut, 0, nLength);
	int i = 0, j = 0;
	while (i < len)
	{
		//如果是英文直接复制就可以
		if (*(pText + i) >= 0)
		{
			pOut[j++] = pText[i++];
		}
		else
		{
			wchar_t pbuffer;
			Gb2312ToUnicode(&pbuffer, pText + i);
			UnicodeToUTF8(buf, &pbuffer);
			pOut[j] = buf[0];
			pOut[j + 1] = buf[1];
			pOut[j + 2] = buf[2];
			j += 3;
			i += 2;
		}
	}
	string ret = pOut;
	delete[] pOut;
	return ret;
}
#endif//defined(_WIN32)

} /* namespace Http */
} /* namespace ZL */
<|endoftext|>