CPU

1. CPU

Antonio Donato Filho
Donato100

(usa Ubuntu)

Enviado em 30/01/2018 - 14:31h

Ola.
Gostaria que alguem me ajuda-se a criar uma linha de comando para que um codigo usa-se 4 nucleos da CPU como este:
nice ./factor -cpu 0:3 &
O codigo que estou usando é este | https://rosettacode.org/wiki/Lucas-Lehmer_test#C | já instalei a Biblioteca GMP e compilei com exito g++ mersenne.c -o mersenne.o -L/gmp_install/lib -lgmp
Mais ./mersenne -cpu 0:3 & naõ funcionou.
Antecipadamnte agradeço a que puder ajudar.



  


2. Re: CPU

Fernando
phoemur

(usa Debian)

Enviado em 30/01/2018 - 18:14h

O código que você está usando não permite execução assíncrona, não existe uma linha de comando que vai fazê-lo rodar em todos os núcleos ao mesmo tempo.

Teria que mudar o código... Mas não é difícil de fazer...


3. Re: CPU

Antonio Donato Filho
Donato100

(usa Ubuntu)

Enviado em 30/01/2018 - 18:19h

Como seria?
Lembrando que sou leigo em C.


4. Re: CPU

Hugo Fernandes
Hgfs

(usa Arch Linux)

Enviado em 30/01/2018 - 19:20h

OpenMP é bem simples de implementar. Dá uma procurada aí.


5. Re: CPU

Fernando
phoemur

(usa Debian)

Enviado em 30/01/2018 - 20:27h

Aqui eu fiz uma abordagem mais simples (porém menos eficiente) dos primos mersenne com o teste de lucas_lehmer para que você possa entender.
Utilizei Boost::Multiprecision / GMP e a própria interface de multithreading do C++.
Provavelmente você já tem boost no seu linux instalado default.
Veja como não é complicado:


// g++ -O3 -Wall -o mersenne mersenne.cpp --std=c++14 -lgmp -lpthread
#include <iostream>
#include <vector>
#include <future>
#include <boost/multiprecision/gmp.hpp>

using namespace boost::multiprecision;

// returns 2^exp - 1
mpz_int power(const uint64_t exp)
{
mpz_int number = 2;
for (uint64_t i = 1; i < exp; ++i) {
number *= 2;
}

number--;

return number;
}

// Performs LL test for exp if exp is odd
bool lucas_lehmer(uint64_t exp,
const mpz_int& number)
{
// corner cases
if (exp == 2) {
std::cout << "//**" << number << "**//\n\n";
return true;
}
else if (exp%2 == 0) return false;

// main calc
mpz_int s = 4;

while (exp > 2) {
s = (s*s - 2) % number;
exp--;
}

if (s == 0) {
std::cout << "//**" << number << "**//\n\n";
return true;
}
else return false;
}

auto async_worker(const uint64_t n)
{
std::vector<std::future<bool>> fut;
fut.reserve(n);

for (uint64_t i = 1; i<=n; ++i) {
fut.push_back(std::async(lucas_lehmer, i, power(i)));
}

return fut;
}


int main(int argc, char* argv[])
{
uint64_t n = 43112609;
if (argc > 1) n = std::stoul(argv[1]);

auto vec = async_worker(n);

for (auto& i: vec) {
i.get();
}


return 0;
}


Como estão sendo executadas várias threads ao mesmo tempo, é possível que imprima fora de ordem ou um número em cima do outro, e por isso eu coloquei pra imprimir //** **// antes e depois.
Verifique que vai estar rodando com todos os núcleos...

Resultado parcial aqui:

[phoemur@notebook_lenovo.darkstar ~/teste/teste/teste]$g++ -O3 -Wall -o mersenne mersenne.cpp --std=c++14 -lgmp -lpthread
[phoemur@notebook_lenovo.darkstar ~/teste/teste/teste]$./mersenne
//**3**//

//**//**//**31**//

7**//

127**//

//**8191**//

//**131071**//

//**524287**//

//**2147483647**//

//**2305843009213693951**//

//**618970019642690137449562111**//

//**162259276829213363391578010288127**//

//**170141183460469231731687303715884105727**//

//**6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151**//



6. CPU [resolvido]

Antonio Donato Filho
Donato100

(usa Ubuntu)

Enviado em 30/01/2018 - 20:36h

Genial.
Mais ainda tenho uma dificuldade que é a biblioteca iostream.

donato@donato:~/Área de Trabalho/mersenne/src/objt$ gcc m.c -o m
m.c:3:20: fatal error: iostream: Arquivo ou diretório não encontrado
compilation terminated.
Encontrei este blog e usei o codigo fonte postado nele e a CPU chegou a 380% | https://sergioprado.org/desafio-do-mes-programacao-paralela-com-o-openmp/ |



7. Re: CPU

Fernando
phoemur

(usa Debian)

Enviado em 30/01/2018 - 20:46h

iostream é do C++, stdio.h é do C puro
Meu código é C++

Para compilar é com
g++ -O3 -Wall -o mersenne mersenne.cpp --std=c++14 -lgmp -lpthread

assumindo que seu arquivo é o mersenne.cpp
Ou seja, GCC é para linguagem C, G++ é para C++, (mas também é gcc).


8. Re: CPU

Antonio Donato Filho
Donato100

(usa Ubuntu)

Enviado em 30/01/2018 - 21:31h

Ainda deu um erro:
mersenne.cpp:6:40: fatal error: boost/multiprecision/gmp.hpp: Arquivo ou diretório não encontrado
compilation terminated.

Usei a linhga de comando g++ -O3 -Wall -o mersenne mersenne.cpp --std=c++14 -lgmp -lpthread
Salvei seu script como mersenne.cpp.




9. Re: CPU

Fernando
phoemur

(usa Debian)

Enviado em 02/02/2018 - 19:14h

Donato100 escreveu:

Ainda deu um erro:
mersenne.cpp:6:40: fatal error: boost/multiprecision/gmp.hpp: Arquivo ou diretório não encontrado
compilation terminated.

Usei a linhga de comando g++ -O3 -Wall -o mersenne mersenne.cpp --std=c++14 -lgmp -lpthread
Salvei seu script como mersenne.cpp.



sudo apt-get install libboost-all-dev 



10. CPU [Resolvido]

Antonio Donato Filho
Donato100

(usa Ubuntu)

Enviado em 05/02/2018 - 12:18h

Desculpe o boost não estava instalado,compiloue executou.

//**3//****//

7**//

//**31**//

//**127**//

//**8191**//

//**131071**//

//**524287**//
Seria possivel imprimir somente os expoentes?
M2 M3 M5 M7 M13 M 17 M19.............
Os numeros ficam muito grandes depois de tempo.
CPU 380% +-






11. Re: CPU

Fernando
phoemur

(usa Debian)

Enviado em 05/02/2018 - 22:14h

Mas daí é mais fácil ainda.
Agora veja que se você quiser uma melhor performance você vai ter que melhorar o algoritmo, pois o algoritmo simples desse meu programa é mais lento. É mais pra exemplificar.

Veja os comentários das otimizações que aquele código em C que você colocou executa e por isso é mais rápido:

/* if p is composite, 2^p-1 is not prime */
/* trust the PRP test for these values */
/* If p=3 mod 4 and p,2p+1 both prime, then 2p+1 | 2^p-1. Cheap test. */
/* Do a little trial division first. Saves quite a bit of time. */ /* factor must be 1 or 7 mod 8 and a prime */
/* mpz_mod(V, V, mp) but more efficiently done given mod 2^p-1 */
/* while (n > mp) { n = (n >> p) + (n & mp) } if (n==mp) n=0 */
/* but in this case we can have at most one loop plus a carry */


Dito isso segue o código:

// g++ -O3 -Wall -o mersenne mersenne.cpp --std=c++14 -lgmp -lpthread
#include <iostream>
#include <vector>
#include <future>
#include <boost/multiprecision/gmp.hpp>

using namespace boost::multiprecision;

// returns 2^exp - 1
mpz_int power(const uint64_t exp)
{
mpz_int number = 2;
for (uint64_t i = 1; i < exp; ++i) {
number *= 2;
}

number--;

return number;
}

// Performs LL test for exp if exp is odd
bool lucas_lehmer(uint64_t exp)
{
uint64_t res = exp;

// corner cases
if (exp == 2) {
std::cout << "M" << res << " " << std::flush;
return true;
}
else if (exp%2 == 0) return false;

// main calc
mpz_int s = 4;
mpz_int number = power(exp);

while (exp > 2) {
s = (s*s - 2) % number;
exp--;
}

if (s == 0) {
std::cout << "M" << res << " " << std::flush;
return true;
}
else return false;
}

auto async_worker(const uint64_t n)
{
std::vector<std::future<bool>> fut;
fut.reserve(n);

for (uint64_t i = 1; i<=n; ++i) {
fut.push_back(std::async(lucas_lehmer, i));
}

return fut;
}


int main(int argc, char* argv[])
{
uint64_t n = 43112609;
if (argc > 1) n = std::stoul(argv[1]);

auto vec = async_worker(n);

for (auto& i: vec) {
i.get();
}


return 0;
}




12. Re: CPU

Antonio Donato Filho
Donato100

(usa Ubuntu)

Enviado em 06/02/2018 - 08:38h

phoemur escreveu:

Mas daí é mais fácil ainda.
Agora veja que se você quiser uma melhor performance você vai ter que melhorar o algoritmo, pois o algoritmo simples desse meu programa é mais lento. É mais pra exemplificar.

Veja os comentários das otimizações que aquele código em C que você colocou executa e por isso é mais rápido:

/* if p is composite, 2^p-1 is not prime */
/* trust the PRP test for these values */
/* If p=3 mod 4 and p,2p+1 both prime, then 2p+1 | 2^p-1. Cheap test. */
/* Do a little trial division first. Saves quite a bit of time. */ /* factor must be 1 or 7 mod 8 and a prime */
/* mpz_mod(V, V, mp) but more efficiently done given mod 2^p-1 */
/* while (n > mp) { n = (n >> p) + (n & mp) } if (n==mp) n=0 */
/* but in this case we can have at most one loop plus a carry */


Dito isso segue o código:

// g++ -O3 -Wall -o mersenne mersenne.cpp --std=c++14 -lgmp -lpthread
#include <iostream>
#include <vector>
#include <future>
#include <boost/multiprecision/gmp.hpp>

using namespace boost::multiprecision;

// returns 2^exp - 1
mpz_int power(const uint64_t exp)
{
mpz_int number = 2;
for (uint64_t i = 1; i < exp; ++i) {
number *= 2;
}

number--;

return number;
}

// Performs LL test for exp if exp is odd
bool lucas_lehmer(uint64_t exp)
{
uint64_t res = exp;

// corner cases
if (exp == 2) {
std::cout << "M" << res << " " << std::flush;
return true;
}
else if (exp%2 == 0) return false;

// main calc
mpz_int s = 4;
mpz_int number = power(exp);

while (exp > 2) {
s = (s*s - 2) % number;
exp--;
}

if (s == 0) {
std::cout << "M" << res << " " << std::flush;
return true;
}
else return false;
}

auto async_worker(const uint64_t n)
{
std::vector<std::future<bool>> fut;
fut.reserve(n);

for (uint64_t i = 1; i<=n; ++i) {
fut.push_back(std::async(lucas_lehmer, i));
}

return fut;
}


int main(int argc, char* argv[])
{
uint64_t n = 43112609;
if (argc > 1) n = std::stoul(argv[1]);

auto vec = async_worker(n);

for (auto& i: vec) {
i.get();
}


return 0;
}


Ficou otímo,agradeço
antonio@donato:~/Área de Trabalho/teste$ ./mersenne
MM23 M5 M7 M13 M17 M19 M31 M61 M89 M107 M127 M521 M607 M1279 M2203 M2281 M3217 M4253