Hilfe 1*1 !

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
problembär

Perl-Einzeiler (ginge bestimmt noch kürzer):

Code: Alles auswählen

perl -e 'for(1..10){for $j(1..10){print"\n$_ x $j = ".$_*$j}print"\n"}'
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Laut wc (ohne Optionen aufgerufen) 101 Zeichen mit Golfscript:

Code: Alles auswählen

1:i;{i 10>}{1:j;{j 11<}{j print' x 'print i print' = 'print i j*p j):j;}while n print i):i;}until
Edit: 98 Zeichen :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

derdon hat geschrieben: Edit: 98 Zeichen :)
Wow, da führt ja meine Basic-Variante mit 59 (respektive BJs Anmerkung 57) Zeichen klar 8)

Ok, Die Länge von BlackJacks Assembler Kompilat könnte da drunter liegen...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Das liegt wahrscheinlich erstens an meinem redundanten Einsatz von print und zweitens an der generellen Herangehensweise (die Art, verschachtelte Schleifen zu verwenden statt map / each). Ich bin mir sicher, dass eine Lösung in weniger als 20 Zeichen in Golfscript möglich ist. Ist halt mein erstes Skript in Golfscript. Solche Wettbewerbe eignen sich gut als Übung :)
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Beim golfen kann awk auch gerade so mitmachen:

Code: Alles auswählen

$ awk 'BEGIN{for(i=1;i<=10;++i)for(j=1;j<=10;++j)print i" x "j" = "i*j}'
Sieht aber aus wie alle C-Artigen - bis auf den sprichwörtlich nicht vorhandenen Stringverkettungsoperator.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Immerhin runter auf 81:

Code: Alles auswählen

1:i;{i 10>}{1:j;{j 11<}{j' x 'i' = 'i j*++++puts j):j;}while n print i):i;}until
BlackJack

@Hyperion: Naja, eigentlich zählt ja die Quelltextgrösse und da ist das Assemblerprogramm viel zu gross um Konkurrenzfähig zu sein.

Das übersetze Assembler-Programm ist 75 Bytes gross (73 Bytes Code + 2 Bytes Startadresse).

Und wenn man die Dateigrösse als Grundlage nimmt, dann ist Dein BASIC-Programm nur 43 Bytes gross, wenn ich mich nicht verzählt habe. Die BASIC-Schlüsselwörter werden jeweils in nur einem Byte gespeichert. Plus Startadresse, 2 Byte-Zeilennummer, 2 Byte Pointer auf den Anfang der nächsten Zeile, Nullbyte zum Abschluss der Zeile und zwei Nullbyte die das Ende des Programms markieren (darauf zeigt der "Nächste-Zeile"-Pointer).

Bei dem BASIC bekommt man den Quelltext selbst aber sogar unter die Dateigrösse, weil man die meisten Befehle bei der Eingabe mit zwei Zeichen abkürzen kann. ``PRINT`` sogar mit einem ``?``:

Code: Alles auswählen

0fOa=1to10:fOb=1to10:?b"x"a"="a*b:nE:?:nE
lunar

Ich hätte noch (SWI-)Prolog zu bieten:

Code: Alles auswählen

timestable(X,Y,XY) :- between(1, 10, Y), between(1, 10, X), XY is X*Y.

writetimestable :-
    forall(timestable(X,Y,XY), writef("%3r * %3r = %3r\n", [X, Y, XY])).
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Das 'Problem' kann man doch parallelisieren:

Code: Alles auswählen

#include <stdlib.h>
#include <stdio.h>
#include <omp.h>

#define MAX 10
int main(void)
{
    puts("Das Einmaleins");
    for(int i=1; i <= MAX; ++i) {
        int result;
#pragma omp parallel for private (result)
        for(int j=1; j <= MAX; ++j) {
            result = i*j;
#pragma omp critical
            {
                printf("%d x %d = %d\n", i, j, result);
            }
        }
    }
    return EXIT_SUCCESS;
}
Ich wollte bloß wissen, ob mein mingw32 opemMP unterstützt (ja, mit dem Parameter '-fopenmp') -und die Ausgabe sieht nicht genau aus wie gefordert ;)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

lol :-) Nice!

Interessant wäre es zu bestimmen, ob bzw. ab welchem Wert von MAX es sich lohnt ;-) Bei einer simplen Multiplikation wird man da wohl erst weit nach der Integer Grenze einen Benefit spüren... :mrgreen:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Damit sich das lohnt, muss man entweder das 'printf()' parallelisieren (?!) oder Berechnung und Ausgabe trennen.
Ich find nur geil, wie (relativ) wenig Programmierer-Aufwand das parallelisieren hier ist.
Wir haben schon 10% vom 21. Jahrhundert hinter uns!
lunar

@b.esser-wisser: Man könnte "result" sinnvollerweise erst in der inneren Schleife deklarieren, dass erspart die "private"-Klausel.
BlackJack

In Python ist das Parallelisieren ja auch kein grosser Programmieraufwand:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from multiprocessing import Pool


def f(n):
    return '\n'.join('%d × %d = %d' % (i, n, i * n) for i in xrange(11))


def main():
    print '\n\n'.join(Pool().map(f, range(11)))


if __name__ == '__main__':
    main()
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben:In Python ist das Parallelisieren ja auch kein grosser Programmieraufwand:
Gibt es da eigentlich eine gute Beschreibung, inwiefern das etwas bringt? Ich habe immer mir unverständliches bezüglich des GILs gelesen, aus dem ich mitnahm, dass Parallelisieren in Python quasi nix bringt. Würde mich mal interessieren, da etwas fundiertes, aber für mich verständliches zu lesen :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Eine gute Beschreibung wüsste ich jetzt auch nicht, aber das GIL ist doch recht simpel erklärt: Python-Bytecode wird in CPython immer nur von einem Thread gleichzeitig ausgeführt. Und alle `n` Bytecodes wird das GIL potentiell einem anderen Thread übertragen. Zum Abfragen und Festlegen von `n` gibt es `sys.[gs]etcheckintervall()`. Wenn man in CPython also mit Threads parallelisieren will, kann immer nur ein Thread Bytecode ausführen. Blockierende IO-Funktionen geben das GIL vor Ablauf der `n` Bytecodes frei und in C implementierte Funktionen können das GIL auch aufgeben und damit tatsächlich parallel zu Bytecode oder anderen C-Funktionen laufen.

Bei `multiprocessing` werden mehrere Prozesse gestartet und die können dann auch Bytecode parallel ausführen. Mit dem Nachteil, das die Argumente und Ergebnisse über Prozessgrenzen hinweg übermittelt werden müssen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben:Blockierende IO-Funktionen geben das GIL vor Ablauf der `n` Bytecodes frei und in C implementierte Funktionen können das GIL auch aufgeben und damit tatsächlich parallel zu Bytecode oder anderen C-Funktionen laufen.
Ah, ok. Das beudetet also, dass wenn eine Funktion den GIL nicht vorher freigibt, eine Parallelisierung keinen Benefit gibt, richtig?
BlackJack hat geschrieben: Bei `multiprocessing` werden mehrere Prozesse gestartet und die können dann auch Bytecode parallel ausführen. Mit dem Nachteil, das die Argumente und Ergebnisse über Prozessgrenzen hinweg übermittelt werden müssen.
Das kostet vermutlich deutlich mehr Rechenzeit und verbraucht auch mehr Ressourcen generell, oder? Würde also eher bei solchen Prozessen sinnvoll sein, die eine große Datenmenge separat bearbeiten können oder auch nicht ständig sich mit anderen Threads austauschen müssen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Zur ersten Frage: Wenn das GIL nicht freigegeben wird, dann findet effektiv ja keine Parallelisierung statt. :-)

Und ja, `multiprocessing` bringt am meisten wenn die Teilaufgaben möglichst unabhängig sind und wenig direkten Datenaustausch untereinander erfordern.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

'multiprocessing' started zusätzliche Interpreter*, da gibt's dann entsprechend mehrere GILs, 'threading' nutzt nur einen interpreter, einen GIL und AFAIK nur einen Prozessor(-kern).
Aber ohne threading hat man auch kaum einen/keinen Vorteil von C-Funktionen, die den GIL freigeben.

* Deshalb ist unter Windows dann die 'if __name__ == "__main__"' notwendig, s. docs
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Da frage ich mich doch mal, wie das dann andere Maschinen, z.B. die JVM lösen? Und bei Jython dürfte es dann ja eigentlich leichter sein, mittels threading Performance zu gewinnen, da die JVM ja keinen GIL kennt.

Ich seh schon wieder die Diskussion abgleiten vom Thema - ok, den OP haben wir eh verschreckt oder durch die Antworten auf Seite eins eine Lösung für die Schule gegeben :mrgreen:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@b.esser-wisser: Bei CPython's `threading` werden ganz normale Threads verwendet, die laufen also grundsätzlich auch parallel und auf allen Prozessoren/Kernen. Nur eben durch das GIL Bytecode immer nur in einem Thread zu einer gegebenen Zeit. Wenn man mehrere Threads zum Beispiel mit `numpy`-Aufrufen hat, die das GIL freigeben, dann laufen diese Operationen potentiell auch parallel auf mehreren Prozessoren/Kernen.

@Hyperion: Das GIL gibt es in CPython weil man sonst für jedes Objekt für den Referenzzähler ein Lock bräuchte und bei jedem Verändern des Referenzzählers -- und das passiert ja im Grunde bei jeder Übergabe des Objekts als Argument -- diese Veränderung durch das Lock schützen müsste. Das wurde wohl auch mal probiert, aber das Ergebnis war deutlich langsamer als CPython mit GIL. Und Guido hat sinngemäss angesagt "GIL abschaffen ist okay -- aber es darf dadurch im normalen Ein-Thread-Fall nicht langsamer werden".

Bei Java gibt es kein GIL, weil die Speicherbereinigung da nicht mit Referenzzählern arbeitet. Die Speichervewaltung benötigt dafür mehr Speicher und gibt den Speicher für die meisten Objekte nicht so "zeitnah" wieder frei wie CPython.
Antworten