C++Guns – RoboBlog blogging the bot

30.04.2017

Modellbahn Veränderungen

Filed under: Allgemein — Tags: — Thomas @ 20:04

Seit über zwei Jahren steht die Anlage nun im Wohnzimmer... und staubt ein. Auf der Oberfläche ist sie eigentlich fertig. Die Gleise sind schon lange verlegt. Die Häuser gestellt, die Strassen gemalt und der Rasen gestreuselt.
Was fehlt ist die Elektronik.
Vor ein paar Monaten hatten wir einen Rückschlag mit der automatischen Wendezugsteuerung. Irgendein Transistor ist wohl durchgebrannt - trotz Sicherung. Wir hatten beschlossen die IC Steuerung durch Relais zu ersetzen. Aber es zieht sich alles länger als gewünscht.

Man darf dabei nicht das große Ziel aus den Augen verlieren. Die Weihnachtsausstellung in der dritten Dezemberwoche im Rathaus, wo wir unsere Anlage präsentieren wollen. Natürlich voll automatisiert. Allerdings nimmt die Anlage im kleinen Raum viel Platz ein, und steht fast 7 Tage herum, bis ich Sonntags mal ein oder zwei Stunden komme und Teste oder Kabel verlege. Um der Sache neuen Anreiz zu geben, und um den Termin einzuhalten, haben wir beschlossen dass die Anlage umzieht, zu mir in den Keller.
Das bietet eine Reihe von Vorteilen:
Ich kann auch unter der Woche einfach mal Abend noch für eine halbe Stunde runter in den Keller gehen und etwas testen.
Oder in Ruhe die Relais Platinen etwas weiter löten.
Sonntags ist mehr Zeit für Sommer-Dinge.
Der ein oder andere hat Interesse bekundet, und man kann sich spontan auch unter der Woche treffen und weiter bauen.

Nachteile gibt es allerdings auch:
Ich muss den Keller aufräumen -_- Okay, das ist streng genommen kein Nachteil, sondern dringend nötig.
Der Transport. Das Ding ist 2x1x0.3m und muss irgendwie bewegt werden. Und mein Kellerabteil ist nicht groß. Es wird wohl nur ein Gang von 60cm breite bleiben.

Aber in der Summe bin ich zufrieden mit der Entscheidung. Es muss vorwärts gehen und es gilt noch einige Relais zu verlöten.

27.04.2017

C++ Guns - Record the result of a boolean expression

Filed under: Allgemein — Tags: — Thomas @ 12:04

Habt ihr euch schon immer einmal gefragt, welche Bedingung in einer if() denn letztlich wahr wurde? Hier ist ein einfacher Weg das zu protokollieren.


inline bool test(const bool b, bool& p) {
  p = b;
  return b;
};

void func() {
  double x = 7;

// I thinks this is the best
    bool p1 = x>5;
    bool p2 = x<10;
    if(p1 and p2) {

// Or choose from this
//  bool p1 = false, p2 = false;
//  if(p=x>5 and p2=x<10) {
//  if(test(x>5, p1) and test(x<10, p2)) {
    if(p1) {
      cout << "p1 was true\n";
    }
    if(p2) {
      cout << "p2 was true\n";
    }
  }
}

Thanks to Juan Jimenez.

26.04.2017

C++ Guns - Fortran forall

Filed under: Allgemein — Tags: — Thomas @ 11:04

Diesen Post möchte ich mit einem kürzlich aufgetretenen Problem in Fortran beginnen.
In Fortran gibt es das forall keyword. Damit ist es möglich Schleifen zu bauen, wie die do Schleife, nur dass es möglich ist, forall Schleifen parallel abzuarbeiten.
Eine Vorraussetzung dafür ist folgende: Wenn data der Vector ist, auf den parallel gearbeitet werden soll, dann müssen die Operationen auf data(i) und data(j) mit i != j unabhängig voneinander sein.
Das ist, für das Beispiel, welches ich hier vorstellen möchte, der Fall.

Beispiel: Jeder Punkt im Array soll transformiert, und in einem neuen Array abgespeichert werden. Hier ist die erste native Implementation:


program LLL
  use naaaah
  implicit none
  integer :: i
  type(Point2D), allocatable :: data(:), data2(:)
  real :: x
  
  allocate(data(100))
  allocate(data2(100))
  
  forall(i=1:size(data))
    x = data(i)%x * cos(data(i)%y)
    data2(i)%x = x
    data2(i)%y = data(i)%y
  end forall
end program

Und die Compiler Fehlermeldung

x = data(i)%x * cos(data(i)%y)
Warning: The FORALL with index ‘i’ is not used on the left side of the assignment at (1) and so might cause multiple assignment to this object

Das ist vollkommen richtig, WENN die forall Schleife parallel ausgeführt wird, so wird parallel auf x geschrieben. Aber x ist nur ein scalar. Daher der Fehler. Abhilfe würde schaffen, x als Array zu declarieren. Aber hier gehen bei HPC sofort alle roten Alarmglocken an und die Notbremse wird gezogen.
Okay.
Untersuchen wir jetzt das Stück Code mal nach dem "Was aber nicht Wie" Prinzip. WAS soll der Code machen? Hm keine Ahnung. WIE macht er es? Er multipliziert x in Abhängigkeit von y. Okay das ist alles, was man wissen muss, um den Code umzuschreiben. Nennen wir die neue Funktion, welche obige Multiplikation ausführt als "toLLL". Damit sieht der Code so aus:


pure function toLLL(point) result(LLLPoint)
  implicit none
  type(Point2D), intent(in) :: point
  type(Point2D) LLLpoint
  
  LLLpoint%x = point%x * cos(point%y*DEGRAD)
  LLLpoint%y = point%y
end function

forall(i=1:size(data))
  data2(i) = toLLL(data(i))
end forall

Nun compiliert der Code ohne Fehler! Warum? Weil die vermeintliche Variable x nicht mehr temporär vorkommt. Lass es mich nochmal verdeutlichen. Im alten Code hatten wir so etwas:


xTemp = xalt*fac;
xneu = xTemp

Und im neuen Code haben wir so etwas


xneu= xalt*fac;

Es gibt also keine temporäre Zwischenvariablen die irgendwie von Hand verwaltet werden müsste. PLUS, der Code ist lesbarer geworden. PLUS der Code ist performanter, da er u.U. parallel ausgeführt werden kann. Ich will nicht behaupten, dass durch das Einführen einer neuen Funktion der Code mehr Richtung Funktionale Programmierung geht. Aber er ist definitiv besser. Das wäre es erst, wenn die Funktion toLLL als Funktionsparamter mit übergeben würde. Hier ist die Grenze von Fortran erreicht. Ohne Templates muss für jede generische Variante von Point2D eine neue Funktion toLLL geschrieben werden. Und das inlinen über mehrere Compilations Units hinweg ist auch nicht möglich.

In C++ gibt es natürlich die selbe Art von Problem, aber sie können leicht gelöst werden. Von Hand geschriebene Schleifen funktionieren natürlich immer. Aber, sobald Parallelisierung in's Spiel kommt. Egal auf welcher Art und Weise auch immer, ist es nicht mehr so einfach wie früher. Parallelisierung bedeutet auf viele Kleinigkeiten achten, auf die man vorher nicht achten musste. Aber wir leben ja nicht im Mittelalter. Wie haben Programme, welche die Checks für uns durchführen. Wir müssen sie nur benutzen.
Ein Beispiel dafür wäre std::transform Hier wird keine Schleife mehr explizit aufgeschrieben. Es wird nur noch gesagt WAS getan werden sollen. Das transformieren von data mit Funktion toLLL nach data2.
Hier das komplette C++ Programm


#include <vector>
#include <algorithm>
#include <cmath>
#include <iostream>

using namespace std;

constexpr const double DEGRAD = M_PI/180.0;

struct Point2D {
  double x, y;
};

Point2D toLLL(const Point2D& point) {
  return {point.x*cos(point.y*DEGRAD), point.y};
}
  

int main() {
  vector<Point2D> data(180), data2(180);
  for(size_t i=0; i < 180; ++i) {
    data[i].x = 180;
    data[i].y = -90.0+i;
  }
  
  transform(std::execution::par, begin(data), end(data), begin(data2), toLLL);
  
  for(const Point2D& p : data2) {
    cout << p.x << " " << p.y << "\n";
  }
}

Der ersten Parameter von transform bestimmt, ob der Datensatz parallel oder sequentiell abgearbeitet werden soll. Das Einführen der Funktion toLLL verhindert temporäre Variablen, und die Funktion wird als Parameter übergeben. Das generalisieren der Funktion toLLL auf einem Point Datentyp mit beliebiger Dimension und fundamentalen Type (int,float) ist nun leicht. Beispiel:


template<class Point>
Point toLLL(const Point& point) {
  Point LLLpoint = point;
  LLLpoint[0] *= cos(LLLpoint[1]*DEGRAD);
  return LLLpoint;
}

14.04.2017

Garten - Es grünt

Filed under: Allgemein — Tags: — Thomas @ 11:04

Im Vordergarten fing es an zu grünen. Leider nicht überall da, wo ich gesät haben, und auch nicht so dicht wie erhofft. Beim bewässern mit der Gießkanne hab ich wohl viele Samen weg geschwemmt. Und bei der anderen kahlen Stelle hat Sushi gebuddelt. Nunja.

rasengruent

Im Hintergarten hab ich auch alles weggerupft was nicht hingehört und neue Samen ausgetragen. Ein paar alte Grashalme stehen noch rum. Hoffentlich werden sie nicht zum Problem. Aber mehr hoffe ich, dass der Schattenrasen sich auch wirklich im Schatten wohl fühlt.

hintergartensamen

Ein letzter vergammelter Apfel war im Baum noch von letztem Jahr zu finden.

apfelvergammelt

Und ansonsten grünt es bei uns. In Grün, Blass und Lila.

gruenfarben

01.04.2017

Silberlinge und Lichtschranken

Filed under: Allgemein — Tags: — Thomas @ 18:04

Die Lichtschranken endgültig zum laufen zu bringen hat zwar ewig gedaurt, aber der Erfolg ist Unser! Eigentlich war es nur eine nicht angeschlossene Abschirmung, falsche Belegung der Klemmen und mal weiss mit weiss vertauscht. Dann war der Verstärker einer Lichtschranke noch zu stark eingestellt, aber ich konnte ihn mit einem 220kOhm Widerstand dämpfen.

Zur Belohnung durften die Silberlinge noch einmal auftreten. Doch bei der Zugzusammenstellung ist dem Lokführer ein Denkfehler unterlaufen...

zuzusammenstellungsfail

Es ist jetzt auch bekannt wo kleine Lokomotiven schlafen ;)

loksschalfen

Powered by WordPress