Parallel computing using ATMEGA328 chips

Hi there,

I'm going to make an Arduino "cluster" for Parallel Computing. Calculating digits of irrational numbers to be exactly (each slave calculates a different irrational number), maybe even coming up for an equation that comes close to the irrational numbers in N digits.

Let's say I want to use 10 (more if possible with I2C) Arduino Mini's per sub cluster (or even bare ATMEGA328P chips, I prefer those chips over the Mini's) as slaves and the master of the sub cluster will be another ATMEGA328P, it'll collect the usefull outputs of the slaves and sends it to the main master, a Nodemcu which will send it to a storage device on the network. So maximum of 11 devices connected to 1 Arduino sub master(10 transmitting (more if possible), 1 receiving).

What the slaves do: Calculate digits of a irrational numbers via a formula with a variable which increases every calculation, then compares it's output and calculates the difference between the output and desired output, if the output is better (percentage wise) than it's previous output, it'll get send to the Nodemcu which will store it on a device in the network.

Also some slaves will "calculate" the best formula for calculating digits of irrational numbers, if it's better then the already used formula, it'll get changed.

Will I2C be "good enough"? I have feeling that the communication would not run smoothly and that I need an I2C buffer chip like the PCA9600.

Let me hear what you think :)

I'll be here,

Is this just a proof of concept? If so why 10 devices, why not save your money and use the smallest number of devices possible that gives a working system?

If you really want something with a useful amount of processing power then you should be looking for processors with GHz clock speeds.

Yes this is an early proof of concept, the number 10 just appeared in my head when I first thought the number of chips I needed. Currently I'm researching which irrational number I want to calculate with this "cluster". The idea is to have each chip calculate a different irrational number, for example using the formula pi: 10^x * sin(180 / 10^x), with 10^x it goes faster, not the best but it'll work. And yes, I'll prefer the minimum amount of devices that gives a working system, but I set the maximum of devices per sub cluster to 10.

Alot will change.

I don't need the fastest clock speed, 16 MHz is good enough. Using the formula, (10^x) * sin(180 / (10^x)), when x>10 the first 19 digits of PI are already correct. Furthermore, the slave will not send the results everytime, after an n (n>5) amount of calculations and comparisations between the desired output and the output, it'll get send to the master which will put it in a text file, which later gets manually inserted into excel.

Using the formula, (10^x) * sin(180 / (10^x)), when x>10 the first 19 digits of PI are already correct

Show your code which does that (in code tags).

If ^ is the exponentiation operator, when x>10 the value of 10^x is extremely large which means that 180/(10^x) is extremely small. That, in turn means that sin(180/(10^x)) is arbitrarily close to 180/(10^x). The end result is that as x gets larger, (10^x) * sin(180 / (10^x)) -> (10^x) * 180 / (10^x) -> 180.

Where did you get that formula from?

Pete

el_supremo:
Show your code which does that (in code tags).

If ^ is the exponentiation operator, when x>10 the value of 10^x is extremely large which means that 180/(10^x) is extremely small. That, in turn means that sin(180/(10^x)) is arbitrarily close to 180/(10^x). The end result is that as x gets larger,
(10^x) * sin(180 / (10^x)) → (10^x) * 180 / (10^x) → 180.

Where did you get that formula from?

Pete

Hi,

I got the formula from http://mathforum.org/library/drmath/view/54089.html.

Since it’s still an early proof of concept version, I haven’t made the code yet. You are right. It is supposed to be x * sin(180/x), remember that it is in radials. This code will work.
The idea is to roughly calculate for 1<x<(2^15), which the ATmega328 will be able to do.

Since you asked for a code, I’ll provide one, I’m not able to check / try the code for faults yet since I don’t have any test subjects :slight_smile: currently.

It only has the calculations atm, not the I2C code etc.

I’m sure that I made mistakes / created errors in this code:

#define PI 3.141592653589793238462643383279 // first 30 decimals of pi
int x = 1;
int tries = 10;
int formula;
int bestper = 0;   //so the first run of the loop works
long bestdif= 100; //so the first run of the loop works
void setup()
{ // nothing in here yet
}
void loop()
{
	while(tries>0){
	formula = x * sin(180/x);
	per= (PI/formula)*100;
	dif= PI-formula;
	if(dif<bestdif){ //since if the dif<bestdif, per>bestper and should get updated.
		bestdif=dif; 
		bestper=per;
	}
	x++;
	tries--;
	}
	if(tries=0){
		// upload best result after 10 tries. Upload: x,bestdif,bestper
		tries = 10; // to continue the loop
	}
	
}

flier: I'm sure that I made mistakes / created errors in this code:

define PI 3.141592653589793238462643383279 // first 30 decimals of pi

So a decimal with 30 places, what are you expecting the compiler to do with that ?

Arduino supports only float variables, which have at most 7 significant digits.

Consider using the BigNumber library for arbitrary precision calculations.

srnet: So a decimal with 30 places, what are you expecting the compiler to do with that ?

A more precise estimate for the difference between output and desired output.

jremington: Arduino supports only float variables, which have at most 7 significant digits.

Consider using the BigNumber library for arbitrary precision calculations.

Thanks for your advice, I'll use it in the code.

That formula isn't going to do you any good either. As x tends to infinity, x*sin(180/x) tends to 180. If you use PI instead of 180, then as x tends to infinity, x*sin(PI/x) tends to PI. But that has to be the dumbest way of calculating PI, because you need to know the value of PI before you can calculate it.

Pete

el_supremo: That formula isn't going to do you any good either. As x tends to infinity, x*sin(180/x) tends to 180.

Pete

I got this information from:https://math.stackexchange.com/questions/930402/why-does-y-x-sin-frac180x-approach-pi

limx→∞[x⋅sin(180x)]
=limx→∞[sin(180x)x−1]
=limx→∞⎡⎣cos(180x)⋅−180x2−x−2⎤⎦
=limx→∞[180cos(180x)]
Now you can argue that since limx→∞180x=0 and cos(0)=1 that limx→∞cos(180x)=1. So
limx→∞[180cos(180x)]=180⋅1=180
And since 180 degrees is the same as π radians, we have shown mathematically just what you have witnessed on your calculator.

And how well does that work, on the Arduino with 6 digits of accuracy (22/7 is good to 4 digits, rounded)?

If you use a calculator set to use degrees, then x*sin(180/x) will tend to PI as x tends to infinity. But the sin function on Arduino only uses radians which requires that you convert 180/x to radians, which is PI/x. You still end up calculating PI when you already know its value.

If you want to calculate PI, a common way to do it is 4*atan(1). atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + (x^9)/9 - ..... atan(1) = 1 - 1/3 + 1/5 - 1/7 + 1/9 - ..... As you add more terms, atan(1) produces successively better approximations to PI/4.

Another number you could calculate is e (2.7182818.....). e = 1 + 1 + 1/2! + 1/3! + 1/4! .....

But, as @jremington has pointed out, on Arduinos which only use single precision float, the best you are going to get from this is 7 digits of precision.

Pete

Thanks for the explanation Pete Ill look into using those codes.

I’ve looked into the BigNumbers section and found this that calculates e in around 100 digits:

#include "BigNumber.h"

static int DIGITS = 103;

void print_bignum (bc_num x)
{
 char *s=bc_num2str(x);
 Serial.println (s);
 free(s);
}

void setup ()
{
 Serial.begin (115200);
 Serial.println ();
 Serial.println ();
 bc_init_numbers ();  // initialize library

 char buf [10]; 

 // some big numbers
 bc_num n= NULL, e = NULL, one = NULL;

 // the number: 1
 bc_str2num (&one, "1", DIGITS);

 e = bc_copy_num (one);
 n = bc_copy_num (one);

 for (int j = 1; j <= 200; j++)
 { 
   bc_num E = bc_copy_num (e);
   bc_num i = NULL;
   sprintf (buf, "%i", j);
   bc_str2num(&i, buf, DIGITS);
   bc_multiply (i, n, &n, DIGITS);  // n is i! (factorial of i)
   bc_free_num (&i);
   bc_num inverse = NULL;
   bc_divide (one, n, &inverse, DIGITS);
   bc_add (inverse, e, &e, DIGITS);
   bc_free_num (&inverse);
   if (bc_compare (e, E) == 0)  // sequence has converged
     break;
   bc_free_num (&E);
 }

 print_bignum (e);
} // end of setup

void loop () { }

I strongly believe Ill be able to change this code to calculate pi etc.

But where this topic started: Would I2C be “good enough” for the transfer of output, I have my concerns that if I send the 100 digits of e it’ll overflow.

The I2C protocol doesn't care what data you are sending, but the I2C library probably will require that you send no more than 32 characters at a time - IIRC the buffer is 32 characters.

Pete

el_supremo:
The I2C protocol doesn’t care what data you are sending, but the I2C library probably will require that you send no more than 32 characters at a time - IIRC the buffer is 32 characters.

Pete

Thanks Pete,

32 characters looks good enough for the difference and percentage.