Pokazywanie postów oznaczonych etykietą profiler. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą profiler. Pokaż wszystkie posty

5 października 2013

[C++] Debugowanie metaprogramów - Templight 2.0

Na tegorocznej (2013) konferencji C++Now, pojawił się bardzo interesujący wykład na temat debugowania/profilowania metaprogramów z wykorzystaniem Templight 2.0 (patch-a na kompilator clang).
Strona projektu:
Nakładania patch-a jest proste, aczkolwiek kompilacja trochę trwała. Na samym początku miałem problem związany z błędem podczas linkowania clang-a. Rozwiązaniem okazało się zwiększenie pamięci do 2GB dla mojej wirtualnej maszyny (VritulBox). Poniżej wszystkie kroki (skopiowane ze strony projektu).
svn co http://llvm.org/svn/llvm-project/llvm/branches/release_32 llvm

cd llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/branches/release_32 clang
cd ../..

cd llvm/tools/clang/tools
svn co http://llvm.org/svn/llvm-project/clang-tools-extra/branches/release_32 extra
cd ../../../..

cd llvm/projects
svn co http://llvm.org/svn/llvm-project/compiler-rt/branches/release_32 compiler-rt
cd ../..

cd llvm/tools/clang
patch -p0 -i ~/templight.diff
cd ../../..

mkdir build (for building without polluting the source dir)
cd build
../llvm/configure
make
Aby skompilować narzędzie (wykorzystuje Qt oraz graphviz) trzeba było doinstalować kilka paczek:
sudo apt-get install graphviz
sudo apt-get install libgraphviz-dev
sudo apt-get install qt-sdk

# Ścieżki do bibliotek
export QTDIR=/usr/share/qt4
export MANPATH=$QTDIR/doc/man:$MANPATH
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
PATH=$QTDIR/bin:$PATH

# Budowanie
cd ProfileDataViewer
qmake
make
Jeżeli w programie korzystamy z szablonów np. dostarczonych przez bibliotekę standardową wyników może być całkiem sporo (może być tu przydatny breakpoint - program Templar). Na początku pojawił się także problem z brakiem widoczności "bits/c++config.h" przez mojego clang-a (ponieważ korzystałem z iostream). Rozwiązaniem było dodanie dodatkowej flagi dla kompilatora:
Proces kompilacji:
# Problem
~/poligon/build/Debug+Asserts/bin/clang++ -templight main.cpp
/usr/lib/gcc/i686-linux-gnu/4.7/../../../../include/c++/4.7/iostream:38:10: fatal error: 'bits/c++config.h' file not found

# Fix
~/poligon/build/Debug+Asserts/bin/clang++ -I/usr/include/i386-linux-gnu/c++/4.7/ -templight main.cpp
Kompilator wygeneruje dla nas plik xml, którym należy nakarmić jeden z programów go analizujących np. Templar (debugger). Przykład, prosty program na obliczanie silni - 5!.
template <int N>
struct factorial
{
    enum { value = N * factorial<N-1>::value };
};

template <>
struct factorial<1>
{
    enum { value = 1 };
};

template <>
struct factorial<0>
{
    enum { value = 1 };
};

int main()
{
    factorial<5>::value;
    return 0;
}
A poniżej graf wygenerowany podczas analizy. Break na factorial<3>::value.

24 marca 2013

python -m (library module as a script)

Python posiada przydatną opcję, z którą można wykonać swoje programy (-m), czyli wykonanie modułu jako skryptu:
-m mod : run library module as a script (terminates option list)
Do nauki posłuży prosty program obliczający ciąg Fibonacciego, ale filtrujący po liczbach nieparzystych. Dodatkowo stworzyłem testy dla dwóch funkcji.
import unittest

def add(f1, f2):
    return f1 + f2

def swap(f1, f2):
    f3 = add(f1, f2)
    return f2, f3

def print_odd(num):
    print 'Odd fibo ', num

def fibo(f1 = 0, f2 = 1):
    [print_odd(num) for num in [f1, f2] if num % 2]
    for _ in xrange(20):
        f1, f2 = swap(f1, f2)
        if f2 % 2:
            print_odd(f2)

class TestSequenceFunctions(unittest.TestCase):
    def setUp(self):
        pass

    def test_add(self):
        self.assertEqual(add(2, 1), 3)

    def test_swap(self):
        self.assertEqual(swap(1, 2), (2, 3))

fibo()
Jednym z takich, przydatnych wbudowanych modułów jest profiler (przydatna instrukcja). Jak widać punkcja print_odd(), została zwołana tylko 14 razy, bo tyle jest nieparzystych liczb, wśród pierwszych 20-tu elementów ciągu.
$ python -m cProfile asdf.py

         57 function calls in 0.007 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.007    0.007 asdf.py:1(<module>)
       20    0.000    0.000    0.000    0.000 asdf.py:1(add)
        1    0.000    0.000    0.007    0.007 asdf.py:11(fibo)
       20    0.000    0.000    0.000    0.000 asdf.py:4(swap)
       14    0.007    0.001    0.007    0.001 asdf.py:8(print_odd)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
Drugi przydatny moduł, o którym się dowiedziałem służy do wykonywania testów jednostkowych.
$ python -m unittest discover --pattern=asdf.py

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK