Boost Spirit: αργή βελτιστοποίησης την ανάλυση

ψήφοι
2

Είμαι νέος στο Πνεύμα και να ωθήσει σε γενικές γραμμές. Προσπαθώ να αναλύσει ένα τμήμα ενός αρχείου VRML που μοιάζει με αυτό:

point
            [
            #coordinates written in meters.
            -3.425386e-001 -1.681608e-001 0.000000e+000,
            -3.425386e-001 -1.642545e-001 0.000000e+000,
            -3.425386e-001 -1.603483e-001 0.000000e+000,

Το σχόλιο που αρχίζει με # είναι προαιρετική.

Έχω γράψει μια γραμματική, που λειτουργεί καλά, αλλά η διαδικασία ανάλυσης λαμβάνει για μεγάλο χρονικό διάστημα. Θα ήθελα να βελτιστοποιήσετε να τρέχει πολύ πιο γρήγορα. κωδικό μου μοιάζει με αυτό:

struct Point
{
    double a;
    double b;
    double c;

    Point() : a(0.0), b(0.0), c(0.0){}
};

BOOST_FUSION_ADAPT_STRUCT
(
    Point,
    (double, a) 
    (double, b)
    (double, c)
)

namespace qi   = boost::spirit::qi;
namespace repo = boost::spirit::repository;

template <typename Iterator>
struct PointParser : 
public qi::grammar<Iterator, std::vector<Point>(), qi::space_type>
{
   PointParser() : PointParser::base_type(start, PointGrammar)
   {
      singlePoint = qi::double_>>qi::double_>>qi::double_>>*qi::lit(,);
      comment = qi::lit(#)>>*(qi::char_(a-zA-Z.) - qi::eol);
      prefix = repo::seek[qi::lexeme[qi::skip[qi::lit(point)>>qi::lit([)>>*comment]]];
      start %= prefix>>qi::repeat[singlePoint];     

      //BOOST_SPIRIT_DEBUG_NODES((prefix)(comment)(singlePoint)(start));
   }

   qi::rule<Iterator, Point(), qi::space_type>              singlePoint;
   qi::rule<Iterator, qi::space_type>                       comment;
   qi::rule<Iterator, qi::space_type>                       prefix;
   qi::rule<Iterator, std::vector<Point>(), qi::space_type> start;
};

Η ενότητα που έχω την πρόθεση να αναλύσει, βρίσκεται στη μέση του κειμένου εισόδου, γι 'αυτό πρέπει να παραλείψετε το τμήμα του κειμένου, προκειμένου να πάρει σε αυτό. Μου υλοποιηθεί με τη χρήση των συμφωνιών επαναγοράς :: ζητούν . Είναι αυτός ο καλύτερος τρόπος;

Τρέχω το πρόγραμμα ανάλυσης με τον ακόλουθο τρόπο:

std::vector<Point> points;
typedef PointParser<std::string::const_iterator> pointParser;   
pointParser g2; 

auto start = ch::high_resolution_clock::now();  
bool r = phrase_parse(Data.begin(), Data.end(), g2, qi::space, points); 
auto end = ch::high_resolution_clock::now();

auto duration = ch::duration_cast<boost::chrono::milliseconds>(end - start).count();

Για να αναλύσει περίπου 80k εγγραφές στο κείμενο εισόδου, χρειάζεται περίπου 2,5 δευτερόλεπτα, το οποίο είναι αρκετά αργή για τις ανάγκες μου. Η ερώτησή μου είναι ένας τρόπος για να γράψει τους κανόνες ανάλυσης σε περισσότερες βελτιστοποιημένο τρόπο ώστε να είναι (πολύ) πιο γρήγορα εκεί; Πώς μπορώ να βελτιώσω την εν λόγω εφαρμογή σε γενικές γραμμές;

Είμαι νέος στο Πνεύμα, έτσι κάποια εξήγηση θα ήταν πολύ ευπρόσδεκτη.

Δημοσιεύθηκε 06/10/2015 στις 11:07
πηγή χρήστη
Σε άλλες γλώσσες...                            


1 απαντήσεις

ψήφοι
2

Έχω γαντζώθηκε γραμματική σας σε ένα Nonius σημείο αναφοράς και παράγεται ομοιόμορφα τυχαία δεδομένα εισόδου ~ γραμμές 85ια (download: http://stackoverflow-sehe.s3.amazonaws.com/input.txt , 7,4 MB).

  • Σας μέτρηση του χρόνου σε μια κατασκευή απελευθέρωση;
  • χρησιμοποιείτε αργή εισαγωγή του αρχείου;

Κατά την ανάγνωση του αρχείου των προτέρων παίρνω σταθερά ένα χρόνο ~ 36ms για να αναλύσει το σωρό.

clock resolution: mean is 17.616 ns (40960002 iterations)

benchmarking sample
collecting 100 samples, 1 iterations each, in estimated 3.82932 s
mean: 36.0971 ms, lb 35.9127 ms, ub 36.4456 ms, ci 0.95
std dev: 1252.71 μs, lb 762.716 μs, ub 2.003 ms, ci 0.95
found 6 outliers among 100 samples (6%)
variance is moderately inflated by outliers

Κωδικός: δείτε παρακάτω.


Σημειώσεις:

  • Σας φαίνεται σύγκρουση σχετικά με τη χρήση των πλοιάρχων και να αναζητήσουν από κοινού. Θα πρότεινα να απλοποιήσει prefix:

    comment     = '#' >> *(qi::char_ - qi::eol);
    
    prefix      = repo::seek[
                      qi::lit("point") >> '[' >> *comment
                  ];
    

    prefixθα χρησιμοποιήσει το χώρο κυβερνήτη, και να αγνοήσει οποιαδήποτε συμφωνημένα χαρακτηριστικά (λόγω της δηλωμένης τύπου κανόνα). Κάντε commentσιωπηρά μια lexeme με τη ρίψη της πλοίαρχο από τη δήλωση κανόνα:

        // implicit lexeme:
        qi::rule<Iterator>                       comment;
    

    Σημείωση Δείτε Ενισχύστε θέματα πνεύμα καπετάνιο για περισσότερες πληροφορίες.

Live On Coliru

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_seek.hpp>

namespace qi   = boost::spirit::qi;
namespace repo = boost::spirit::repository;

struct Point { double a = 0, b = 0, c = 0; };

BOOST_FUSION_ADAPT_STRUCT(Point, a, b, c)

template <typename Iterator>
struct PointParser : public qi::grammar<Iterator, std::vector<Point>(), qi::space_type>
{
    PointParser() : PointParser::base_type(start, "PointGrammar")
    {
        singlePoint = qi::double_ >> qi::double_ >> qi::double_ >> *qi::lit(',');

        comment     = '#' >> *(qi::char_ - qi::eol);

        prefix      = repo::seek[
            qi::lit("point") >> '[' >> *comment
            ];

        //prefix      = repo::seek[qi::lexeme[qi::skip[qi::lit("point")>>qi::lit("[")>>*comment]]];

        start      %= prefix >> *singlePoint;

        //BOOST_SPIRIT_DEBUG_NODES((prefix)(comment)(singlePoint)(start));
    }

  private:
    qi::rule<Iterator, Point(), qi::space_type>              singlePoint;
    qi::rule<Iterator, std::vector<Point>(), qi::space_type> start;
    qi::rule<Iterator, qi::space_type>                       prefix;
    // implicit lexeme:
    qi::rule<Iterator>  comment;
};

#include <nonius/benchmark.h++>
#include <nonius/main.h++>
#include <boost/iostreams/device/mapped_file.hpp>

static boost::iostreams::mapped_file_source src("input.txt");

NONIUS_BENCHMARK("sample", [](nonius::chronometer cm) {
    std::vector<Point> points;

    using It = char const*;
    PointParser<It> g2;

    cm.measure([&](int) {
        It f = src.begin(), l = src.end();
        return phrase_parse(f, l, g2, qi::space, points);
        bool ok =  phrase_parse(f, l, g2, qi::space, points);
        if (ok)
            std::cout << "Parsed " << points.size() << " points\n";
        else
            std::cout << "Parsed failed\n";

        if (f!=l)
            std::cout << "Remaining unparsed input: '" << std::string(f,std::min(f+30, l)) << "'\n";

        assert(ok);
    });
})

Γραφική παράσταση:

εισάγετε περιγραφή της εικόνας εδώ

Μια άλλη έξοδο τρέξιμο, ζουν:

Απαντήθηκε 06/10/2015 στις 12:43
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more