mpi parallelizing a nested loop dynamically - c

I'm trying to parallelize this code (changing only the main, not the heavy function) using mpi- with a dynamic task pool approach. i would like some help with the implementation. which parameters should i pass between master and slaves? how?
thank you
#include <stdio.h>
#include <math.h>
#define HEAVY 1000
#define SIZE 40
#define RADIUS 10
// This function performs heavy computations,
// its run time depends on x and y values
// DO NOT change the function
double heavy(int x, int y) {
int i, loop;
double sum = 0;
if (sqrt((x - 0.75*SIZE)*(x - 0.75*SIZE) + (y - 0.25*SIZE)*(y - 0.25*SIZE)) < RADIUS)
loop = 5*x*y;
else
loop = y + x;
for (i = 0; i < loop*HEAVY; i++)
sum += sin(exp(cos((double)i / HEAVY)));
return sum;
}
// Sequencial code to be parallelized
int main(int argc, char *argv[]) {
int x, y;
int size = SIZE;
double answer = 0;
for (x = 0; x < size; x++)
for (y = 0; y < size; y++)
answer += heavy(x, y);
printf("answer = %e\n", answer);
}
i tried to create a task pull in the size of 'size', but i didnt know what should be the values inside it and how to pass it right

Related

Is there a way to make a function for calculating 10 to the x exponent in C? "ten_to_the(x exponent)"

I need to multiply a number by 10 to the (x) power, depending on the exponent I may require.
I know there is a function, in the <math.h> library, but I was wondering if I could make my own function to achieve basically the same but only for 10, not any number. It´s for course homework, but since we haven´t been told about this library, I want to try to achieve it without said power() function.
Here's my code; it does compile, but I get some weird number instead of the intended 5000.
#include <cs50.h>
#include <stdio.h>
int ten_to_the(int n);
int main(void) {
int x = 50;
x *= ten_to_the(2);
printf("%.i\n", x);
}
int ten_to_the(int n) {
n = 1;
for (int i = 0; i < n; i++) {
n *= 10;
}
return n;
}
Because you multiple n by 10 on each iteration of the loop, i < n can never become true. In practice, n keeps getting bigger until it overflows and becomes negative.
Use another variable to keep track of the result separate from the number of iterations you need to calculate.
Instead of this:
int ten_to_the(int n)
{
n = 1;
for (int i = 0; i < n; i++)
{
n *= 10;
}
return n;
}
This:
int ten_to_the(int n)
{
int result = 1;
for (int i = 0; i < n; i++)
{
result *= 10;
}
return result;
}

executing if else statement by probability

I have a program that looks something like this. i would like to run my if else query by probability.
int main() {
int probability = 70; //<-- 70% probability to run if statement
for (int i = 0; i < 5e5; i++){
if (???){
...
}
else {
...
}
}
return 0;
}
As #user3386109 pointed out, if(rand() % 100 < chance) is probably more then sufficient. As explained in the C FAQ, when the random number generated is not a multiple of 100, here, this method causes some numbers to appear more than others. If it falls on the range where it makes a difference, the easiest thing is to draw another number.
#include <stdio.h>
#include <stdlib.h> /* rand() */
#include <time.h> /* clock() */
/** http://c-faq.com/lib/randrange.html */
static int rand_0_99(void) {
unsigned int x = (RAND_MAX + 1u) / 100;
unsigned int y = x * 100;
unsigned int r;
do r = rand();
while(r >= y);
return r / x;
}
int main(void) {
size_t i, cumulate = 0;
const size_t replicas = 1000000;
const int chance_100 = 70;
/* Seed the linear congruential generator with the time. */
srand((unsigned)clock());
for(i = 0; i < replicas; i++) {
const int decision = rand_0_99() < chance_100;
if(decision) cumulate++;
}
printf("P(r < %d/100) = %lu/%lu\n",
chance_100, (unsigned long)cumulate, (unsigned long)replicas);
return EXIT_SUCCESS;
}
This is overkill, but may be needed, especially when 100 is close to RAND_MAX.

Hopalong fractals, checking c synatx

I have written following code in order to produce simple list of double pairs to import in plot program.
#include <stdio.h>
#include <math.h>
int main(void)
{
int i;
double x=2,y=3;
for(i = 0; i < 1000; i++){
x = y- x/fabs(x)*sqrt(fabs(x+0.7));
y = 0.3-x;
printf("%5.4f , %5.4f\n" ,x,y);
}
return 0;
}
I don't get what I expect from this functions. Instead of hopalong fractal I get linear progression graph. Is this only syntax error?
When you assign y, you use the new value of x, which has just been updated. The calculation requires the x value from the last step. Make a copy and use that:
int main(void)
{
double x = 2;
double y = 3;
int i;
for(i = 0; i < 1000; i++) {
double xx = x;
x = y - x/fabs(x)*sqrt(fabs(x + 0.7));
y = 0.3 - xx;
printf("%5.4f , %5.4f\n" ,x,y);
}
return 0;
}

Print the Cantor Set using recursion in C

I'm trying to print the Cantor Set to the console using 'x', but I'm stuck at the 2nd recursion which no matter what I do, just doesn't execute.
The Idea is to first initialize the matrix using clearP() so I don't have to worry about the whitespaces. After that I load the array with 'x' chars using the depth as a [y] value.
To remove the middle segment on each line I use secondLength and smallerLength. Now the reason to use 2 recursive calls is, that for example on depth 1 it removes the middle part once, on depth 2 twice, on depth 3 four times and so on. However I just can't get the 2nd recursion to execute, which is why my output looks like this.
Any advice where I'm making mistakes?
#include <stdio.h>
#include <math.h>
#define WIDTH 27
#define HEIGHT (int)(cbrt(WIDTH)+1)
void clearP(char p[WIDTH][HEIGHT]){
int x, y;
for(x = 0; x<WIDTH; x++){
for (y=0;y<HEIGHT;y++){
p[x][y] = ' ';
}
}
}
void printP(char p[WIDTH][HEIGHT]){
int x, y;
for(y = 0; y<HEIGHT; y++){
for (x=0;x<WIDTH;x++){
printf("%c",p[x][y]);
}
printf("\n");
}
}
void cantor(char p[WIDTH][HEIGHT],int start,int end, int depth){
int smallerLength = end / 3;
int secondStart = start + (smallerLength * 2);
for (int x = start; x<end ; x++){
p[x][depth] = 'x';
}
if (depth == HEIGHT){
return;
}
cantor(p, start, smallerLength, depth+1);
cantor(p, secondStart, smallerLength, depth+1);
}
int main(){
char canvas[WIDTH][HEIGHT];
clearP(canvas);
cantor(canvas, 0, WIDTH, 0);
printP(canvas);
}
I think you got your height and width mixed up in print.
try this
void printP(char p[WIDTH][HEIGHT]){
int x, y;
for(x = 0; x<HEIGHT; x++){
for (y=0;y<WIDTH;y++){
printf("%c",p[x][y]);
}
printf("\n");
}
}
A point in [0, 1] is in the Cantor set if it's ternary representation doesn't contain any 1's (that is, only 0's and 2's). This observation allows you to output the d-level representation by looking at the first d digits of the fractional part of i/n in base 3, without needing arrays.
#include <stdio.h>
void cantor(int n, int d) {
for (int i = 0; i < n; i++) {
int in = 1;
int x = i;
for (int j = 0; j < d; j++) {
in = in && !(3*x >= n && 3*x < 2*n);
x = (3*x)%n;
}
putchar(in ? 'x' : ' ');
}
putchar('\n');
}
int main(int argc, char *argv[]) {
for (int d = 0; d < 5; d++) {
cantor(81, d);
}
return 0;
}

What's wrong with my Mandelbrot set code?

I'm trying to implement the Mandelbrot set in C, but I'm having a weird problem. My code is as follows:
#include <stdio.h>
#include <math.h>
#include <complex.h>
int iterate_pt(complex c);
int main() {
FILE *fp;
fp = fopen("mand.ppm", "w+");
double crmin = -.75;
double crmax = -.74;
double cimin = -.138;
double cimax = -.75; //Changing this value to -.127 fixed my problem.
int ncols = 256;
int nrows = 256;
int mand[ncols][nrows];
int x, y, color;
double complex c;
double dx = (crmax-crmin)/ncols;
double dy = (cimax-cimin)/nrows;
for (x = 0; x < ncols; x++){
for (y = 0; y < nrows; y++){
double complex imaginary = 0+1.0i;
c = crmin+(x*dx) + (cimin+(y*dy)) * imaginary;
mand[x][y] = iterate_pt(c);
}
}
printf("Printing ppm header.");
fprintf(fp, "P3\n");
fprintf(fp, "%d %d\n255\n\n", ncols, nrows);
for (x = 0; x < ncols; x++) {
for (y = 0; y < nrows; y++){
color = mand[x][y];
fprintf(fp, "%d\n", color);
fprintf(fp, "%d\n", color);
fprintf(fp, "%d\n\n", color); //Extra new line added, telling the ppm to go to next pixel.
}
}
fclose(fp);
return 0;
}
int iterate_pt(double complex c){
double complex z = 0+0.0i;
int iterations = 0;
int k;
for (k = 1; k <= 255; k++) {
z = z*z + c;
if (sqrt( z*conj(z) ) > 50){
break;
}
else
++iterations;
}
return iterations;
}
However, the output of this program, which is stored as a ppm file looks like this:
Thanks for your help!
Try setting cimax to -0.127, I'm also working on this project and it seems to do the trick ;)
The code looks good.
But your starting rectangle doesn't look right!
you are using
Real ranage [ -.75 , -.74 ]
Imag range [ -.138 , -.75 ]
are you sure this is what you intended? It seems like an awfully stretched y-scale to me.
Also, standard mandelbrot algorithms tend to use
magnitude > 2
rather than 50.
as an escape check. Though this shouldn't affect the actual shape of the set.
BTW, there's no point in computing the sqrt of z*conj(z). Simply square the expressions on both sides of the inequality, giving if (z*conj(z) > 2500) and you've boosted the performance.

Resources