|
|
|
|
T400, regelmäßig im Einsatz.
|
|
|
|
|
|
|
|
|
|
|
dieses android und was die verschiedenen hersteller alles damit anstellen schockiert mich immermehr... :/
|
|
|
|
|
|
|
Ich kenne keinen Hersteller und kein ROM das standardmäßig so ausgeliefert wird.
|
|
|
|
|
|
|
Außerdem muss man doch neue Geräte einmalig bei entsperrtem Gerät zulassen
|
|
|
|
|
|
|
| Zitat von csde_rats
X61s ist doch nicht alt. Ich hab nen 240, das ist alt
| |
Ich habe letztes Jahr nochmal das R52 "fit" gemacht.
|
|
|
|
|
|
|
Spoiler - markieren, um zu lesen:
240... nicht X240
|
|
|
|
|
|
|
|
|
|
|
Interessanter Artikel über Astronomie bei Heise.
// edit
Nach mehreren Versuche, hartem Neuladen und dem selben Ergebnis in Epiphany und Firefox bin ich endlich dahinter gekommen. Dass der "Accept"-Button erst funktioniert, wenn ich nach unten scrolle
Danke JetBrains
|
[Dieser Beitrag wurde 2 mal editiert; zum letzten Mal von hoschi am 11.06.2018 16:32]
|
|
|
|
|
|
Du bist auch einer der Anwender, die Hinweise nicht lesen?
|
|
|
|
|
|
|
Können wir das auf den Begriff "Nutzungsbedingungen" einschränken?
|
|
|
|
|
|
|
Traxer kann das doch bestimmt aus dem Ärmel schütteln: warum ist __mulsc3 langsamer als __muldc3 (Multiplikation von komplexen Zahlen mit einfacher bzw. doppelter Genauigkeit; ein Faktor 2 ist erstmal eine gute Annahme)? Der Code ist abgesehen von single vs. double precision doch erstmal identisch (clang/compiler-rt), bzw. wird vom gleichen Makro erzeugt (gcc/libgcc).
|
[Dieser Beitrag wurde 1 mal editiert; zum letzten Mal von [CSF]Omega am 11.06.2018 17:56]
|
|
|
|
|
|
Weil DP meistens fast genau zweimal langsamer ist als SP.
|
|
|
|
|
|
|
Das ist aber die falsche Richtung.
¤: Single Precision ist langsamer als Double Precision.
|
[Dieser Beitrag wurde 1 mal editiert; zum letzten Mal von [CSF]Omega am 11.06.2018 17:57]
|
|
|
|
|
|
Oh
Klingt komisch - ich würde mir da mal den generierten Code genauer anschauen, ob da was merkwürdig riecht.
|
|
|
|
|
|
|
Warum nutzt du es denn? Embedded Kram ohne fpu?
|
|
|
|
|
|
|
| Zitat von Oli
Warum nutzt du es denn? Embedded Kram ohne fpu?
| |
Da hast auch Du Dich von irgendeinem Softbla in der GCC Doku in die Irre leiten lassen. Stimmt vielleicht auch in sofern, als das man im Allgemeinen nicht für CPUs mit direkter Unterstützung für komplexe Zahlen kompiliert, und dann komplexe Zahlen halt als Paar von zwei reellen Zahlen behandeln muss. __mulsc3/__muldc3 entsprechen der Definition aus dem C-Standard, die Multiplikation der reellen Zahlen findet natürlich auf der CPU statt.
|
[Dieser Beitrag wurde 1 mal editiert; zum letzten Mal von [CSF]Omega am 11.06.2018 18:19]
|
|
|
|
|
|
Ah, okay. Darf ich trotzdem fragen, woran du arbeitest?
Ich nutze ja std::complex
|
|
|
|
|
|
|
Rewrite in Rust!11
|
|
|
|
|
|
|
Ich eigentlich auch. std::complex wird für float, double und long double mit den entsprechenden C Typen spezialisiert (eventuell erst ab C++11, hab schon wieder vergessen was ich heute so alles überflogen habe). Die Multiplikation zweier std::complex führt also abhängig vom Typ zu einer der obigen Funktionen, und da ist halt aufgefallen, dass diese Multiplikation (eigentlich natürlich einige tausende davon) für double schneller ist als für float. Was der naiven Erwartung (siehe rats) widerspricht.
|
|
|
|
|
|
|
| Zitat von [CSF]Omega
Traxer kann das doch bestimmt aus dem Ärmel schütteln: warum ist __mulsc3 langsamer als __muldc3?
| |
nö, kann er jetzt so spontan nicht.
der code für die llvm builtins ist gleich, bis auf den typ.
es gibt da aber nen eintrag, dass das mit -ffast-math und dem finite math flag langsamer laufen soll, als ohne. scheint irgendwas mit dem optimizer zu sein, der dann bestimmte code teile nicht mehr optimieren kann. (nur kurz überflogen)
probier das mal mit und ohne.
andernfalls kann ich mir das spontan nur dadurch erklären, dass irgendeines der buildins, die in den mathe funktionen genutzt werden irgendeinen trick anwendet, der nur bei doubles greift. alternativ: kann natürlich auch sein, dass da irgendwas zu exzessiven register clears führt, wenn das auf nem 64 bit chip läuft, also das dort immer die restlichen 32 bit manuell genullt werden.
ansonsten keine ahnung, ich würde mal mit den compiler flags rumspielen, mir nen sehr kleines test case schreiben und dann den asm code anschauen. spätestens da solltest du sehen können, warum sich das komisch verhält.
was std::complex und co angeht, die nutzen intern auch „nur“ die builtins, dass kommt aufs gleiche raus. im fall der libs, die llvm/gcc mitliefern ist das auch der gleiche code der da läuft.
|
|
|
|
|
|
|
Ich kann nichts zu den Funktionen sagen!
| Zitat von [CSF]Omega
¤: Single Precision ist langsamer als Double Precision.
| |
Welche Hardware? Es soll Systeme geben, auf denen Double generell schneller ist als Float. Damit wäre das eventuell erklärbar.
Mehr noch, ich bin so erzogen worden immer Double zu verwenden, wegen der höheren Genauigkeit und weil der Performancenachteil im Vergleich zu Float vernachlässigbar ist. Ausnahme bestätigen, wie immer, die Regel.
|
|
|
|
|
|
|
ja, der performancenachteil ist definitv vernachlässigbar, sind nur irgendwo zwischen 25 und 70 prozent, pro instruction. das gilt auch nur, wenn man die nicht mehr existente fpu nutzen würde, andernfalls ist das schlimmer.
|
|
|
|
|
|
|
Pro Instruktion? Sollten bei moderner Hardware erst dann signifikante Unterschiede auftreten, wenn die Daten nicht mehr aus dem Cache kommen?
| Zitat von Traxer
wenn man die nicht mehr existente fpu nutzen würde
| |
|
[Dieser Beitrag wurde 1 mal editiert; zum letzten Mal von hoschi am 11.06.2018 19:44]
|
|
|
|
|
|
Also, die ganze Sache ist natürlich noch etwas verwirrender, als ich das bis jetzt dargestellt habe.
Eigentlich gilt für das Multiplizieren von komplexen Zahlen ungefähr das hier:
|
Code: |
x = a + i*b
y = c + i*d
z = x*y = (a*c - b*d) + i*(a*d + b*c)
|
|
Wenn man dem C99-Standard folgt ist das ganze schon nicht mehr ganz so einfach, man muss nämlich jeden einzelnen Real- und Imaginärteil darauf überprüfen, ob er eine Zahl ist, oder halt +/- NaN oder +/- Infinity. Nach irgendeiner festen Regel werden diese Nichtzahlen dann in den Real- und Imaginärteil des Ergebnisses übernommen. Diese Sonderfälle machen das ganze so komplex, dass das ganze nicht mehr geinlined wird, sondern in die erwähnten Funktionen ausgelagert wird. Für die Addition ist sowas nicht nötig, da hier Real- und Imaginärteil separat behandelt werden können, d.h. nur die beiden Realteile können den neuen Realteil beeinflussen, da gelten dann die normalen Regeln für Fließkommazahlen.
Hier das Testprogramm:
|
Code: |
#include <algorithm>
#include <chrono>
#include <complex>
#include <iostream>
#include <random>
#include <vector>
template<typename T>
const char*
prettyType();
template<>
const char*
prettyType<float>()
{
return "float";
}
template<>
const char*
prettyType<double>()
{
return "double";
}
#ifdef direct
#warning "use C complex numbers in sum"
extern "C" {
__complex__ float __mulsc3(float, float, float, float);
__complex__ double __muldc3(double, double, double, double);
}
template<typename T>
inline
std::complex<T>
sum(const std::vector<std::complex<T>>&);
template<>
inline
std::complex<float>
sum<float>(const std::vector<std::complex<float>>& v)
{
const size_t length = v.size();
__complex__ float sum = 0.0;
for (unsigned int i = 0; i < length; ++i)
for (unsigned int j = 0; j < length; ++j)
sum += __mulsc3(v[i].real(), v[i].imag(), v[j].real(), v[j].imag());
return std::complex<float>(__real__ sum, __imag__ sum);
}
template<>
inline
std::complex<double>
sum<double>(const std::vector<std::complex<double>>& v)
{
const size_t length = v.size();
__complex__ double sum = 0.0;
for (unsigned int i = 0; i < length; ++i)
for (unsigned int j = 0; j < length; ++j)
sum += __muldc3(v[i].real(), v[i].imag(), v[j].real(), v[j].imag());
return std::complex<double>(__real__ sum, __imag__ sum);
}
#else
template<typename T>
inline
std::complex<T>
sum(const std::vector<std::complex<T>>& v)
{
const size_t length = v.size();
std::complex<T> sum;
for (unsigned int i = 0; i < length; ++i)
for (unsigned int j = 0; j < length; ++j)
sum += v[i] * v[j];
return sum;
}
#endif
template<typename T, const size_t length = 100>
void
test()
{
std::mt19937 rndgen(123456);
std::uniform_real_distribution<T> dist(0.0, 12345.6789);
std::vector<std::complex<T>> v(length);
std::generate(v.begin(), v.end(), [&dist,&rndgen]() { const T r = dist(rndgen); const T i = dist(rndgen); return std::complex<T>(r, i); });
auto start = std::chrono::system_clock::now();
std::complex<T> s = sum(v);
auto end = std::chrono::system_clock::now();
const std::chrono::duration<double> time(end-start);
std::cout << "sum for " << prettyType<T>() << " took " << time.count() << " s: " << s << std::endl;
}
int
main(int argc, char* argv[])
{
test<float>();
test<double>();
}
|
|
Erstmal nur die GCC (GCC4.9, devtoolset-3, RHEL6) Ergebnisse, clang ist nochmal extra speziell.
|
Code: |
$ g++ -std=c++11 -O3 bla.cc -o bla
$ ./bla
sum for float took 3.15104 s: (4.42991e+12,4.53069e+15)
sum for double took 0.994963 s: (3.35809e+12,3.08329e+16)
|
|
Für den Test ist das sogar nochmal schlimmer als in der eigentlich Anwendung, dort finde ich nur einen Faktor zwei zugunsten von double, hier ist es sogar ein Faktor drei um den double schneller ist als float. Aber, in der Tat mit -ffast-math:
|
Code: |
$ g++ -std=c++11 -O3 bla.cc -o bla -ffast-math
$ ./bla
sum for float took 0.431998 s: (4.42991e+12,4.53069e+15)
sum for double took 0.445863 s: (3.35809e+12,3.08329e+16)
|
|
Hier sieht man also das naiv erwartete Nicht-Langsamer-Sein von floats. Ich bin mir aber gerade nicht sicher, ob -ffast-math wirklich eine Option für den echten Anwendungsfall ist, da muss ich wohl nochmal genauer nachlesen was damit alles ausgeschaltet wird.
Dann mal auf zu clang (Apple LLVM 9.1). Das ist jetzt ein anderer Rechner, deshalb sind die Zeiten nicht direkt vergleichbar:
|
Code: |
$ clang++ -O3 -std=c++11 bla.cc -o bla
$ ./bla
sum for float took 1.79012 s: (4.42991e+12,4.53069e+15)
sum for double took 2.4145 s: (3.35809e+12,3.08329e+16)
|
|
Für clang ist also auch ohne -ffast-math float wie zu erwarten schneller als double. Stellt sich raus, dass das clang den Aufruf von __mul?c3 wrappt (sinngemäß):
|
Code: |
z=x*y:
value_type e = x.real()*y.real - x.imag()*y.imag()
value_type f = x.real()*y.imag + x.imag()*y.real()
if (isnan(e) || isnan(f))
z = __mul?c3(x.real(), x.imag(), y.real(), y.imag());
else
z = e + i*f
|
|
Diese Berechnung kann geinlined werden, und nur falls die einfache Berechnung der neuen Real- und Imaginärteile irgendwo NaN ergibt, wird die Berechnung an __mul?c3 übergeben. Dafür beschleunigt -ffast-math zwar immer nach den ganzen Test, float wird aber langsamer als double.
|
Code: |
$ clang++ -O3 -std=c++11 bla.cc -o bla -ffast-math
$ ./bla
sum for float took 1.36594 s: (4.55313e+12,3.77658e+15)
sum for double took 0.579735 s: (3.35809e+12,3.08329e+16)
|
|
Und letztendlich: Zwingen wir doch clang mal dazu trotzdem __mul?c3 zu benutzen.
|
Code: |
$ clang++ -O3 -std=c++11 bla.cc -o bla -Ddirect
$ ./bla
sum for float took 2.18363 s: (4.42991e+12,4.53069e+15)
sum for double took 2.34664 s: (3.35809e+12,3.08329e+16)
|
|
Für doubles eigentlich keine Änderung gegenüber der Ausgangslage (ohne -ffast-math), für floats wird das ganze dagegen langsamer. Hier könnte man also die Extrakosten für den Funktionsaufruf abschätzen. Für den GCC dagegen keine Änderung gegenüber der Ausgangslage:
|
Code: |
$ g++ -std=c++11 -O3 bla.cc -o bla -Ddirect
$ ./bla
sum for float took 3.33212 s: (4.42991e+12,4.53069e+15)
sum for double took 0.945766 s: (3.35809e+12,3.08329e+16)
|
|
Nach all den Tests bin ich also genau so kluk wie vorher, denn -ffast-math, was die Lösung für gcc wäre, hat bei clang den entgegengesetzten Effekt. Vielleicht probiere ich mal in GCC eine ähnliche Abkürzung einzubauen, wie clang sie hat.
Funfact am Rande: GCC und clang interpretieren
|
Code: |
std::generate(v.begin(), v.end(), [&dist,&rndgen]() { return std::complex<T>(dist(rndgen), dist(rndgen)); });
|
|
unterschiedlich, einmal werden die dist(rndgen) von rechts nach links ausgeführt, einmal von links nach rechts, deshalb:
|
Code: |
std::generate(v.begin(), v.end(), [&dist,&rndgen]() { const T r = dist(rndgen); const T i = dist(rndgen); return std::complex<T>(r, i); });
|
|
|
|
|
|
|
|
|
Hmja. Das mit dem Inlining ist mir vorhin auch aufgefallen, hatte die Funktionen in den Godbolt gesteckt, und ihn nicht dazu bringen können, __mul... zu inlinen (was mich überrascht hat). [Wär auch ein sehr schneller weg gewesen ohne Compiler auf diesem Rechner hier den Code zu sehen]
Sinngemäß:
#include <complex.h>
complex float muls(float a, b, c, d)
{
return __mul...
}
+ muld.
Das ist allerdings auch einfach unspezifiziert (oder IB, weiß ich gerad nicht).
|
|
|
|
|
|
|
|
|
|
Audio-Kram
|
Disclaimer: Ich habe total null Ahnung von Audio.
Ich höre "viel" scheinbar schlecht aufgenommenes Audio (Podcasts, Youtube..). Was mir dabei tierisch auf den Keks geht sind so "Spitzen", häufig in Podcasts bei harten Lauten wie in "Zischen", oder bei lautem Lachen.
Wenn ich das Audio etwas lauter habe (also, schon ab so 70% beim Thinkpad) tut das schon in den Ohren weh. Leiser kann ich es aber auch nicht wirklich machen, dann verstehe ich zum Beispiel mit offenen Fenster oder im Auto auf der Autobahn kein Wort mehr.
Bei (ich nehme an) gut abgemischtem Audio habe ich das Problem nicht (Beispielsweise bei Metaebene-Podcasts). Im Auto konnte ich mir mit den Klangeinstellungen des Radios helfen, da haben ich einfach "Höhen" um 9db gesenkt, das geht jetzt so halbwegs. Aber auf meinem Notebook kann ich das nicht.
Lange Geschichte, kurzer Sinn: Kann PulseAudio das auch?
|
|
|
|
|
|
|
|
|
|
|
Schau dir mal PulseAUdio Equalizer oder PulseEffects an.
|
|
|
|
|
|
Thema: Der Linux-Thread 100 != 0x24 ( Ein Kernelupgrade später... ) |