Goldbach Vermutung



  • @Volkard, Bengo, Arcoth: Habe ich alle wichtigen Ideen zur Beschleunigung inkorporiert oder habe ich noch etwas Wichtiges übersehen? Was könnte man sinnvoll parallel laufen lassen? Zehn Zahlen gleichzeitig testen?

    Die Klasse BigInteger bietet auch einen Algo für modexp:

    BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent,	const BigUnsigned &modulus) 
    {
    	BigUnsigned ans = 1, base2 = (base % modulus).getMagnitude();
    	BigUnsigned::Index i = exponent.bitLength();
    	// For each bit of the exponent, most to least significant...
    	while (i > 0) 
    	{
    		i--;
    		// Square.
    		ans *= ans;
    		ans %= modulus;
    		// And multiply if the bit is a 1.
    		if (exponent.getBit(i)) 
    		{
    			ans *= base2;
    			ans %= modulus;
    		}
    	}
    	return ans;
    }
    


  • Erhard Henkes schrieb:

    @Volkard: Gibt es Liars oberhalb 2^64 zum Download?

    Ich kenne keine.



  • Wie gesagt, wuerde ich es nochmal mit einer loopenden Tabelle pobieren, die in den Cache passt um die Teilbarkeit durch die ersten Primzahlen zu pruefen. Das wuerde dann mehrere Divisionen durch eine Division und ein Lookup ersetzen. Gleichzeitig kann man das dann eben auch nutzen um den primes vector viel kleiner zu machen.



  • Ab dem Bereich 10^240 sind wir im Bereich ca. 1h/Geradzahl angelangt:

    10^240, erste Primzahl 2351, t: 2215 s
    10^241, erste Primzahl 2069, t: 3929 s

    Hier findet man eine erste zum Paar passende Primzahl erst über 1000.



  • Das sind etwa 800bit, scheint mir so, als ob man das noch sehr optimieren kann, da mein Computer auch 4096 bit Primzahlen generieren kann.(In weniger als einer Stunde) bei SSL



  • Bengo schrieb:

    Das sind etwa 800bit, scheint mir so, als ob man das noch sehr optimieren kann, da mein Computer auch 4096 bit Primzahlen generieren kann.(In weniger als einer Stunde) bei SSL

    Welchen Zweck hätte eine 4096-Bit-Primzahl bei SSL? Sicher, daß Du da 4096-Bit-Primzahlen berechnen läßt?

    Naja, SEHR optimieren nenne ich das nicht. Klar handoptimiertes asm an manche Stellen, MMX/SSE, Multitreading, damit kann man noch was holen. Mit der riesigen Gefahr, dass man sich dabei verzettelt und einen läppischen Faktor 10 kriegt und dafür Einbußen an der Einfachheit und Wartbarkeit hat und deswegen am Algo spart und billiardenfach lahmer ist.



  • Bitte nicht übersehen, dass wir bei 10^241 mit der ersten Primzahl 2069 in den 3929 Sekunden bei allen Primzahlen von 3 bis 2069 alle entsprechenden Partner "Geradzahl minus erste Primzahl" auf ihre Primzahlfähigkeit prüfen. Im Lookup findet da schon lange nichts mehr, man ist somit auf den kleinen Divisionstest (z.Z. 3 ... 101) angewiesen und auf den Milli-Miller-Rabin. Den Lügnertest kann man natürlich gar nicht erst laden und abschalten über 2^64.

    Ich werde im nächsten Schritt das C++ 11 std::thread einbauen und verschiedene parallele Strategien testen.

    Beispiele:
    - mehrere Geradzahlen parallel auf Goldbach-Vermutung prüfen
    - mehrere erste Primzahlen parallel auf ihren möglichen Primzahl-Partner prüfen (hier findet man aber nicht mehr die erste kleine Primzahl, sondern irgendein Paar)



  • volkard schrieb:

    Bengo schrieb:

    Das sind etwa 800bit, scheint mir so, als ob man das noch sehr optimieren kann, da mein Computer auch 4096 bit Primzahlen generieren kann.(In weniger als einer Stunde) bei SSL

    Welchen Zweck hätte eine 4096-Bit-Primzahl bei SSL? Sicher, daß Du da 4096-Bit-Primzahlen berechnen läßt?

    Naja, SEHR optimieren nenne ich das nicht. Klar handoptimiertes asm an manche Stellen, MMX/SSE, Multitreading, damit kann man noch was holen. Mit der riesigen Gefahr, dass man sich dabei verzettelt und einen läppischen Faktor 10 kriegt und dafür Einbußen an der Einfachheit und Wartbarkeit hat und deswegen am Algo spart und billiardenfach lahmer ist.

    Stimmt hast recht, das RSA Modul hat 4096bit, die Primzahlen dann aber immernoch mehr als 2048bit.



  • Die Thread-Unterstützung habe ich mal eingebaut (noch nicht ideal) und im Bereich 10^120 bis 10^120 + 20 getestet (11 Geradzahlen, 11 Threads). Das läuft gut, man er hält die Ergebnisse in der gleichen Zeit wie vorher die langsamste Zahl in diesem Bereich. 11 Threads sind bei mir mit 12 virtuellen Kernen optimal. Hier das Programm, falls es jemand ausprobieren/optimieren will:

    #include "stdafx.h"  // MS VC++  
    
    #define NOMINMAX     // due to conflict with max() 
    #include <windows.h> // warning: no C++ standard! 
    
    #include <iostream>
    #include <iomanip>
    #include <cstdint>
    #include <cstdlib>
    #include <cassert>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    #include <unordered_set>
    #include <fstream>
    #include <thread>
    #include <mutex>
    #include "BigIntegerLibrary.hh" // https://mattmccutchen.net/bigint/
    
    //#define MILLER_RABIN_LIAR_CHECK
    
    using namespace std;
    
    void setConsole() // windows.h
    {
    	_CONSOLE_SCREEN_BUFFER_INFO info;
    	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    	GetConsoleScreenBufferInfo(handle, &info);
    	COORD c;
    	c.X = std::max<SHORT>(info.dwSize.X, 150);
    	c.Y = std::max<SHORT>(info.dwSize.Y, 1000);
    	SetConsoleScreenBufferSize(handle, c);
    
    	SMALL_RECT RECT;
    	RECT.Left = 0;
    	RECT.Top = 0;
    	RECT.Bottom = std::max(info.srWindow.Bottom - info.srWindow.Top, 40 - 1);
    	RECT.Right = std::max(c.X - 1, 100 - 1);
    	SetConsoleWindowInfo(handle, TRUE, &RECT);
    }
    
    void textcolor(unsigned short color = 15) // windows.h
    {
    	SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), color);
    }
    
    void wait()
    {
    	cout << "Press any key to continue." << endl;
    	cin.clear();
    	cin.ignore(numeric_limits<streamsize>::max(), '\n');
    	cin.get();
    }
    
    mutex mutex_; // for cout 
    
    unordered_set<uint64_t> setLiar;
    uint64_t lastLiar = 0;
    
    uint64_t convertBigToU64(BigUnsigned num)
    {
    	BigUnsigned ZweiHochVierUndSechzig = stringToBigUnsigned("18446744073709551616");
    	assert(num < ZweiHochVierUndSechzig);
    	uint64_t jHi = num.getBlock(1);
    	uint64_t jLo = num.getBlock(0);
    	return (jHi << 32 | jLo);
    }
    
    void convertU64ToBig(uint64_t num, BigUnsigned& b)
    {
    	uint32_t numLo = (uint32_t)(num & 0xFFFFFFFF);
    	uint32_t numHi = (uint32_t)((num >> 32) & 0xFFFFFFFF);
    	b.setBlock(0, numLo);
    	b.setBlock(1, numHi);
    }
    
    //calculates (a * b) % c
    BigUnsigned mulmod(BigUnsigned a, BigUnsigned b, BigUnsigned mod)
    {
    	BigUnsigned x = 0;
    	BigUnsigned y = a % mod;
    
    	while (b > 0)
    	{
    		if (b % 2 == 1)
    		{
    			x = (x + y) % mod;
    		}
    		y = (y * 2) % mod;
    		b /= 2;
    	}
    	return x % mod;
    }
    
    BigUnsigned powmod_Volkard(BigUnsigned base, BigUnsigned exp, BigUnsigned modul)
    {
    	//rechnet 'base hoch exp mod modul'
    	BigUnsigned a1 = base, z1 = exp, x = 1, m = modul;
    	while (z1 != 0)
    	{
    		while ((z1 % 2) == 0)
    		{
    			z1 /= 2;
    			a1 = mulmod(a1, a1, m);
    		}
    		--z1;
    		x = mulmod(x, a1, m);
    	}
    	return x;
    }
    
    bool IsProbablyPrime_MillerRabinOptimized(BigUnsigned n)
    {
    	/*
    	example:
    	step: "calculate s and d"
    	n = 1001
    	n-1 = 1000
    	s = 3
    	d = 125
    	1000 / 2^3 = 125
    
    	step: "test with base a"
    	ad = a^d mod n  (cf. function powmod)
    	...
    	*/
    
    	if (n == 2)
    		return true;
    	// "s" is the logarithm to base base 2 of the biggest number 2^s dividing n-1
    	// d = (n-1)/(2^s)
    	// calculate d and s
    	BigUnsigned d = n - 1;
    	BigUnsigned s = 0;
    	while ((d & 1) == 0)
    	{
    		++s; d >>= 1;
    	}
    
    	// We do not use random base a = {2 ... n-1}, but fix it to a = 2
    	BigUnsigned a = 2; // base ("witness")
    	BigUnsigned ad = (powmod_Volkard(a%n, d, n)); // (a^d) mod n
    
    	if (ad == 1)
    		return true; // a^d mod n == 1
    	if ((s > 0) && (ad == (n - 1)))
    		return true; // a^d mod n == -1 (tests (a^d)^(2^0))
    
    					 // test for r = {0 ... s-1}
    	for (BigUnsigned r = 1; r < s; ++r)
    	{
    		// ad is currently ad^(2^(r-1)), thus we square it to get ad^(2^r))
    		ad = mulmod(ad, ad, n);
    		if (ad == (n - 1))
    			return true; // tests (a^d)^(2^(r+1)))
    	}
    	return 0; // false, composite
    }
    
    bool IsPrimeDivisionTest(BigUnsigned number)
    {
    	if (number<2)    return false;
    	if (number == 2)   return true;
    	if (number % 2 == 0) return false;
    	for (BigUnsigned i = 3; i*i <= number; i += 2)
    	{
    		if (number%i == 0) return false;
    	}
    	return true;
    }
    
    bool IsPrime(vector<bool>& primes, BigUnsigned number, BigUnsigned primeLimit, unordered_set<uint64_t>& setLiar)
    {
    	// lookup from bitset (in the RAM)
    	if (number <= primeLimit)
    		return primes[number.toUnsignedLong()];
    
    	// division test with first prime numbers
    	if (
    		/*(number % 2 == 0) || */
    		(number % 3 == 0) || (number % 5 == 0) || (number % 7 == 0) || (number % 11 == 0) ||
    		(number % 13 == 0) || (number % 17 == 0) || (number % 19 == 0) || (number % 23 == 0) ||
    		(number % 29 == 0) || (number % 31 == 0) || (number % 37 == 0) || (number % 41 == 0) ||
    		(number % 43 == 0) || (number % 47 == 0) || (number % 53 == 0) || (number % 59 == 0) ||
    		(number % 61 == 0) || (number % 67 == 0) || (number % 71 == 0) || (number % 73 == 0) ||
    		(number % 79 == 0) || (number % 83 == 0) || (number % 89 == 0) || (number % 97 == 0) ||
    		(number % 101 == 0)
    		)
    	{
    		return false;
    	}
    
    	// Miller-Rabin, not perfect, but fast
    	if (!IsProbablyPrime_MillerRabinOptimized(number))
    	{
    		return false; //
    	}
    	else
    	{
    		if (lastLiar == 0)
    		{
    			return true;
    		}
    
    		BigUnsigned bigLastLiar;
    		BigUnsigned& refBigLastLiar = bigLastLiar;
    		convertU64ToBig(lastLiar, refBigLastLiar);
    
    		if (number > bigLastLiar)
    		{
    			return true;
    		}
    		else
    		{
    			if (setLiar.find(convertBigToU64(number)) != setLiar.cend())
    			{
    				// cout << "ALARM: Miller-Rabin-Liar found: " << number << "  ";
    				// wait();
    				return false; // function tells the truth by failure list (0 ... 2^64), above lastLiar there will be "Prime Hell" again.
    			}
    			return true;
    		}
    	}
    }
    
    void PrimePairFound(vector<bool>& primes, BigUnsigned i, const BigUnsigned primeLimit, unordered_set<uint64_t>& setLiar, bool* retVal)
    {
    	*retVal = false;
    
    	BigUnsigned grenze = i / 2;
    	BigUnsigned a = 0;
    	for (a = 3; a <= grenze; a += 2)
    	{
    		if (IsPrime(primes, a, primeLimit, setLiar) && IsPrime(primes, i - a, primeLimit, setLiar))
    		{
    			*retVal = true;
    			break;
    		}
    	}
    
    	mutex_.lock();
    	cout << i << "  " << setw(5) << a << endl;
    	mutex_.unlock();
    }
    
    int main()
    {
    	setConsole(); // windows.h // big console for large numbers! ^^
    	textcolor(14); // windows.h // 10 = light green, 14 = light yellow
    
    	BigUnsigned startNumber = stringToBigUnsigned("1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
    	BigUnsigned endNumber = stringToBigUnsigned("1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020");
    	const int numberOfThreads = 11; // count of even numbers from start to end = (end - start)/2 + 1
    
    	uint64_t const primeLimit = 2000000; //200000000000;
    	cout << "We generate vector<bool>(primes) up to: " << primeLimit << endl; // (this amount depends on the capability of your RAM)
    
    	vector<bool> primes(primeLimit); // processed numbers;
    	time_t startTime, endTime;       // measuring execution time
    	uint64_t global_count = 0;       // total number of primes
    	time(&startTime);
    
    	// initialize the number array
    	primes[0] = false;
    	primes[1] = false;
    	for (uint64_t i = 2; i<primeLimit + 1; ++i)
    	{
    		primes[i] = true;
    	}
    
    	// sieving loop
    	uint64_t iMax = (uint64_t)sqrt((double)primeLimit) + 1;
    	for (uint64_t i = 2; i<iMax; ++i)
    	{
    		if (primes[i])
    		{
    			for (uint64_t j = 2 * i; j<primeLimit + 1; j += i)
    			{
    				primes[j] = false;
    			}
    		}
    	}
    
    	time(&endTime);
    
    	// count the number of primes
    	for (uint64_t i = 0; i<primeLimit + 1; ++i)
    	{
    		if (primes[i])
    			global_count++;
    	}
    
    	cout << "In " << difftime(endTime, startTime) << " s we found " << global_count
    		<< " prime numbers (2 to " << primeLimit << " )." << endl << endl;
    
    #ifdef MILLER_RABIN_LIAR_CHECK
    	// Prepare Miller-Rabin "Liar-Liste" and detect Goldbach prime pairs with Miller-Rabin test
    	ifstream fileLiar("F:\\Daten\\Miller_Rabin_Liar\\2-SPRP-2-to-64.txt", fstream::in); // https://miller-rabin.appspot.com/
    	cout << "Miller-Rabin Liar file starts to be read from file." << endl;
    	uint64_t count = 0;
    	uint64_t u64LiarNumber = 0;
    	while (!fileLiar.eof())
    	{
    		fileLiar >> u64LiarNumber;
    		// cout << u64LiarNumber << "\t";
    		setLiar.insert(u64LiarNumber);
    		count++;
    	}
    	fileLiar.close();
    	lastLiar = u64LiarNumber;
    	cout << "Miller-Rabin Liar file with " << count << " liars is read." << endl << "Last liar: " << u64LiarNumber << endl << endl;
    #endif // MILLER_RABIN_LIAR_CHECK
    
    	unordered_set<uint64_t>& refSetLiar = setLiar;
    
    #ifdef MILLER_RABIN_LIAR_CHECK
    	cout << "Now Goldbach first prime number pair will be detected:" << endl;
    #else
    	cout << "Now Goldbach probable (no liar list available) first prime number pair will be detected:" << endl;
    #endif
    
    	clock_t zeit1, zeit2, zeit2_old, delta;
    	zeit2 = zeit1 = clock();
    	uint64_t sumTime = 0;
    
    	for (BigUnsigned i = startNumber; i <= endNumber; i += (2 * numberOfThreads))
    	{		
    		bool retVal[numberOfThreads];		
    		vector<thread> t;
    
    		for (int x = 0; x<numberOfThreads; ++x)
    		{
    			retVal[x] = false;		
    			if ((i+2*x) <= endNumber)
    				t.emplace_back(PrimePairFound, primes, i+2*x, BigUnsigned((unsigned long)primeLimit), refSetLiar, retVal + x);
    		}
    
    		for (int x = 0; x < numberOfThreads; ++x)
    		{
    			if ((i + 2 * x) <= endNumber)
    			{
    				t[x].join(); // we have to wait for the result of the thread!
    				if (retVal[x] == false)
    					cout << "Counterevidence found for this number: " << i + 2 * x << endl;							
    			}				
    		}
    
    		zeit2_old = zeit2;
    		zeit2 = clock();
    		delta = zeit2 - zeit2_old;
    		sumTime += delta;
    		cout << "time: " << 1000 * delta / CLOCKS_PER_SEC << " ms" << endl << endl;
    	}
    	cout << "total time: " << sumTime/1000 << " s" << endl << endl;
    	wait();
    }
    

    `We generate vector<bool>(primes) up to: 2000000

    In 0 s we found 148933 prime numbers (2 to 2000000 ).

    Now Goldbach probable (no liar list available) first prime number pair will be detected:

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018 191

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 173

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006 179

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008 181

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016 733

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 613

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 193

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 619

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012 719

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 709

    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014 1153

    time: 237940 ms

    total time: 237 s`



  • Erhard Henkes schrieb:

    Die Thread-Unterstützung habe ich mal eingebaut (noch nicht ideal) und im Bereich 10^120 bis 10^120 + 20 getestet (11 Geradzahlen, 11 Threads). Das läuft gut, man er hält die Ergebnisse in der gleichen Zeit wie vorher die langsamste Zahl in diesem Bereich. 11 Threads sind bei mir mit 12 virtuellen Kernen optimal. Hier das Programm, falls es jemand ausprobieren/optimieren will:

    Hab nur 2 Kerne 😞



  • Hab nur 2 Kerne

    Dann stellst Du die numberOfThreads auf 2, 3 oder 4 (dein OS kümmert sich um das MT Scheduling) ein. Ich baue das noch um, sodass die richtige Threadanzahl verwendet wird und diese auch immer etwas zu schaffen haben. 😉
    Probiere momentan verschiedene Abläufe aus.

    Wichtige Frage: Kann man die Gesamtauslastung (vom Prg aus) des gesamten Programms auf einen gewissen Wert (z.B. 50 oder 80%) einstellen?



  • Hier ein erster Test für 10^240 (!):
    `

    Now Goldbach probable (no liar list available) first prime number pair will be detected:

    ...04 97

    ...16 109

    ...10 103

    ...08 101

    ...14 107

    ...20 113

    ...06 2357

    ...18 3527

    ...00 2351

    ...02 2039

    ...12 5279

    total time: 3654 s`

    Zeitbestimmend bei der Primzahl-Paarsuche ist die Zahl 10^240 + 12, da wir erst bei 5279 fündig werden. Hier könnten vlt. noch mehr Primzahlen (bisher: 3 ... 101) beim Pre-Divisions-Check helfen.

    Man sieht, dass nun die Primzahlabstände (nach unten) von der untersuchten Geradzahl nun auch mehrfach im Bereich über 1000 liegen (bei 10^120 war es nur eine von elf Zahlen). Gibt es hier eine Regel für den Abstand zwischen zwei Primzahlen in Abhängigkeit vom untersuchten Zahlenbereich?

    Dieser Zahlenbereich 10^240 stellt somit in etwa die Grenze dar für das aktuelle Programm. Ich gehe davon aus, dass Goldbach mit seiner Vermutung recht behalten wird. Das Programm ist auch ein hübscher CPU-Stresstest zum Testen neuer PCs. Einfach den Bereich X bis X + 100 (X: sehr große Zahl) berechnen lassen und Zahl der Threads entsprechend auf 51 einstellen.



  • Wichtige Frage: Kann man die Gesamtauslastung (vom Prg aus) des gesamten Programms auf einen gewissen Wert (z.B. 50 oder 80%) einstellen?

    macht man ja üblicherweiße über OS. alternativ kann man es ja mit nem sleep machen und zeit/tickcount nehmen

    edit: so gehts ein wenig bequemer, wenn ichs richtig überflogen habe:
    https://technet.microsoft.com/en-us/library/ff384148.aspx?f=255&MSPPError=-2147217396



  • Ich habe doch noch mal 10^300 geprüft:

    `..04 73

    ..10 79

    ..14 83

    ..02 71

    ..20 89

    ..06 353

    ..12 359

    ..00 347

    ..16 6427

    ..08 3767

    ..18 12149

    total time: 14226 s

    `

    Da in dieser Region der Abstand zur nächsten Primzahl (nach unten) in einem Fall (10^300 + 18) auf fünfstellige Zahlen anwächst, braucht die Berechnung fast 4 Std. Das ruft nun wirklich neue Algos auf den Plan.



  • Irgendwas stimmt mit deinem Multithreading nicht richtig. Ich hab die Diskussion hier nur so halb verfolgt, wollte aber mal das Programm ausprobieren. Neuere gcc Versionen (4.9) beschweren sich über diese Zeile:

    t.emplace_back(PrimePairFound, primes, i+2*x, BigUnsigned((unsigned long)primeLimit), refSetLiar, retVal + x);
    

    Mit einer älteren Version (4.4) compiliert es immerhin. Ausschnitt der Fehlermeldung:

    main.cpp:336:125:   required from here
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<void (*(std::vector<bool>, BigUnsigned, BigUnsigned, std::unordered_set<long unsigned int>, bool*))(std::vector<bool>&, BigUnsigned, BigUnsigned, std::unordered_set<long unsigned int>&, bool*)>’
           typedef typename result_of<_Callable(_Args...)>::type result_type;
    

    Ich denke das Problem ist, dass deine PrimePairFound Funktion einige Parameter als Referenz nimmt. Wenn ich den Code so ändere compiliert es auch mit gcc 4.9:

    t.emplace_back(PrimePairFound, std::ref(primes), i+2*x, BigUnsigned((unsigned long)primeLimit), std::ref(refSetLiar), retVal + x);
    

    Aber selbst wenn es compiliert kriege ich einen Segfault in genau dieser Zeile.



  • Im MS VS 2015 läuft es ohne Probleme. Daher ändere ich da gar nix.



  • Erhard Henkes schrieb:

    Im MS VS 2015 läuft es ohne Probleme. Daher ändere ich da gar nix.

    Nicht gerade die beste Einstellung. Ein Segfault kommt auch nicht einfach so. Irgendwas geht dort wohl ziemlich schief. Warum es bei VS2015 nicht passiert oder man nichts bemerkt weiß ich nicht. Vielleicht versuche ich nacher mal den Fehler einzugrenzen.



  • Ok sorry. Das Problem saß mal wieder vorm Bildschirm. Seit wann muss man pthread dazu linken wenn man std::thread benutzt? Naja läuft jetzt jedenfalls wobei das mit dem std::ref trotzdem nötig war.



  • OK, über den wrapper std::ref kann man reden. Das ist eher eine Verbesserung. Danke für den Hinweis.

    t.emplace_back(PrimePairFound, std::ref(primes), i+2*x, BigUnsigned((unsigned long)primeLimit), std::ref(refSetLiar), retVal + x);
    

  • Mod

    sebi707 schrieb:

    Ok sorry. Das Problem saß mal wieder vorm Bildschirm. Seit wann muss man pthread dazu linken wenn man std::thread benutzt?

    Immer.

    Naja läuft jetzt jedenfalls wobei das mit dem std::ref trotzdem nötig war.

    Jo. Die result_of -Zeile hätte sonst nicht kompiliert, schließlich werden die Argumente mit declval simuliert, welches standardmäßig rvalues produziert.


Anmelden zum Antworten