28 października 2013

Going Native 2013

Zakończyłem oglądanie udostępnionych wykładów z GoingNative 2013. Pojawiło się na niej kilka slajdów z nowościami z C++14, ale żadne wykład nie był mu w całości zadedykowany. Z najfajniejszych (moim zdaniem) wykładów warto wymienić.
  • Writing Quick Code in C++, Quickly - sztuczki z optymalizacją kodu w bibliotece folly rozwijanej przez Facebook-a. Mam nadzieje, że nie będę musiał się nigdy kłopotać takimi szczegółami, nie mówiąc o przykładach, które nie do końca rozumiem. Kilka wniosków z prezentacji
    • Inżynierowie którzy znają architekturę swojego sprzętu piszą lepszy kod
    • "Mierz wszystko!". Aby sprawdzić wydajność programu wynikowego, trzeba badać go z każdej strony: czas wykonani, zużycie pamięci, zużycie energii, ...
    • Jeżeli dobrze zrozumiałem, czas kompilacji kodu może zostać skrócony, przez stosowanie final tam gdzie to możliwe. Niestety gcc i clang nadal nad tym pracują.
  • Don’t Help the Compiler - jak dla mnie tytuł troszkę mylący bo wykład opowiada o najczęstszych błędach jakie popełniają programiści. Garść notatek z prezentacji:
    • Jeżeli zwracamy wynik przez wartość, stosowanie const może wyłączyć move semantic. Nie korzystać z const dla wartości.
    • Wartości zwracane przez rvalue lub rvalue reference np. string& i string&& są tym samym. Czyli referencją do wartości.
    • Nie korzystać z move(), dla obiektów lokalnych które chcemy zwrócić. Jeżeli dobrze rozumiem, gdy zwracamy lokalną zmienną mogą zadziać się dwie rzeczy. Albo kompilator przeniesie (zoptymalizuje) konstrukcje tego obiektu do kodu wywołującego, albo zadziała move semantic (nie trzeba mu pomagać używając move).
    • Czasami korzystanie ze standardowych funktorów z STL-a tworzy bardziej elegancki kod, niż lambda np. std::plus<> itp.
  • An Effective C++11/14 Sampler - dużo ciekawych informacji na temat wątków oraz std::move i std::forward - sam jeszcze eksperymentuje z tym więc będzie osobny wpis.
    • Jeżeli chcemy szybkości (w postaci move semantic), przekazując przez wartość należy zrezygnować z const. To samo dotyczy zwracania. const wymusza kopiowanie!
    • Warto stosować noexcept, gdy to tylko możliwe generowany jest wtedy bardziej zoptymalizowany kod.
  • The Care and Feeding of C++’s Dragons - bardzo ciekawy wykład na temat rozszerzeń do clang-a mających na celu ułatwienie pracy programistom. Poeksperymentuje jak tylko uda się przekompilować clang-a.
  • rand() Considered Harmful - przestroga przed stosowaniem rand() z biblioteki C. Do C++11 trafiła biblioteka służąca do generowanie wartości losowych, bardzo podobna do Boost.Random.
  • C++ Seasoning - jak znajomość algorytmów standardowych (STL), może usprawnić refactoring kodu.
  • Inheritance Is The Base Class of Evil - trudne do zakumania, ale przykład działa na wyobraźnie. Może będzie kiedyś czas, by nad tym spokojnie pokontemplować. 

27 października 2013

[C++Now] Interactive, Introspected C++ at CERN

Fajny wykład (z konferencji C++Now 2013) na temat pracy w CERN, oraz narzędzie/oprogramowania jakie się tam wytwarza: iterpreter C++ (projekt cling), oraz bibliotekę ROOT na potrzeby fizyków.

6 października 2013

[Win] Redmond Path - edycja ścieżek przeszukiwania

Kolega pokazał mi bardzo fajne narzędzie, pozwalające na edycję ścieżek przeszukiwania w Windows. Wraz z kolejnymi wersjami systemu, problem miniaturowego okienka, w którym można tego dokonać jakoś nie jest rozwiązywany. Redmond Path jest tutaj wspaniałym udogodnieniem:

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.