2013-09-04 9 views
9

Dostępne są języki zinterpretowane, takie jak Lisp, Tcl, Perl itd., Które ułatwiają zdefiniowanie lambda/proc/sub w kodzie w czasie wykonywania i ocenę to w tej samej sesji.Składanie funkcji według potrzeb i szybkie jej obliczanie

Istnieją skompilowane języki, takie jak C++, które byłyby wykonywane o wiele szybciej niż te interpretowane, jednak zdefiniowanie funkcji w skompilowanym programie podczas wykonywania i wykonanie go nie jest łatwe, jeśli w ogóle możliwe.

Problem polega na tym, aby wykonać następujące czynności:

  1. zdefiniować funkcję w trakcie wykonywania: na przykład, na podstawie wstępnych danych wejściowych czerpać analitycznego modelu danych.

  2. Wykonaj powyższą funkcję szybko w pętli: na przykład zastosuj wyprowadzony model analityczny do analizy danych przychodzących.

Jednym z rozwiązań, które widziałem nie była bardzo ładna:

  1. Procedura reprezentujący analitycznego modelu pochodzi z wbudowanego Tcl na podstawie wstępnych danych wejściowych.

  2. Tablica przeglądowa została stworzona poprzez ocenę procedury w Tcl na tablicy punktów prób, które, optymistycznie rzecz biorąc, obejmowałyby zakres stosowalności.

  3. Tablica wyników została przekazana z interpretera Tcl z powrotem do pliku binarnego (który został opracowany w C++).

  4. Następnie przychodzące dane zostały przeanalizowane poprzez interpolację między wartościami "wystarczająco zbliżonymi" w tabeli odnośników.

Powyższe rozwiązanie działa, ale ma sporo problemów, zarówno koncepcyjnych, jak i obliczeniowych. Zatem pytanie: czy możliwe jest zdefiniowanie funkcji wyłącznie w C++ i udostępnienie jej do wykonania w ramach tej samej sesji środowiska wykonawczego?

Czy można rozumieć koncepcyjnie, jak stworzyć funkcję jako ciąg znaków, skompilować ją w pamięci i jakoś połączyć z powrotem do wykonywanego pliku binarnego?

+0

Istnieje wiele wydajnych kompilatorów Lisp. Istnieją wirtualne maszyny oparte na JIT, takie jak .NET i JVM. Istnieją wbudowane kompilatory C (tcc, clang). Łatwo jest również wygenerować LLVM IR bezpośrednio, z wszystkimi zaletami potężnego kompilatora optymalizującego. –

+1

Nawet interpretatory C++ są szeroko stosowane, zobacz CINT i ROOT. –

Odpowiedz

12

Jeśli chcesz, aby coś działało zaraz po wyjęciu z pudełka, spójrz na numer ExprTK. Jeśli chcesz napisać parser wyrażeń, sprawdź: Boost Spirit.

Alternatywą byłoby stworzenie kodu C++ w locie, skompilowanie go jako biblioteki współdzielonej (wtyczki) i załadowanie go w środowisku wykonawczym. Prawdopodobnie byłoby to najszybsze rozwiązanie.

+0

Dzięki, na pierwszy rzut oka Boost Spirit wygląda obiecująco. Czy wiesz, jak szybko to jest? Czy generuje zoptymalizowany kod binarny, który można wykonać w pętli wystarczająco szybko? – Michael

+0

Analizator składający się z Ducha zazwyczaj tworzy drzewo składni abstrakcyjnej (AST), które jest po prostu agregacją operacji i wartości. Oto przykład: [Przykład Boost Spirit AST] (http: //www.boost.org/doc/libs/1_41_0/libs/spirit/example./qi/calc2_ast.cpp). Dlatego wynik będzie generalnie wolniejszy niż zoptymalizowany skompilowany kod. Jeśli prędkość jest twoją główną troską, powinieneś iść do ostatniej sugestii. – ToniBig

+13

@Michael Boost.Spirit jest ok do analizowania, ale ocena AST będzie wielkim zabójcą w wydajności. Również rozwijanie z Boost.Spirit wymaga dużo cierpliwości, a większość kompilatorów nie radzi sobie z czymś bardziej złożonym niż prosta gramatyka stylu kalkulatora +/-/* - czasy kompilacji są szalenie długie i trzeba robić różne sztuczki, jak łamanie gramatyki do wielu plików itp. –

Powiązane problemy