Skip to content

Commit bf94c35

Browse files
authored
mandelbrot C implementation translated from Zig and Go (#453)
1 parent 3ec0ff0 commit bf94c35

File tree

4 files changed

+365
-0
lines changed

4 files changed

+365
-0
lines changed

Diff for: bench/algorithm/mandelbrot/1-ffi.c

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
//translated from Zig
2+
//
3+
//gcc -O3 -mno-fma -march=native -Wall main.c
4+
//clang -O3 -Wno-deprecated -mno-fma -mllvm -polly -mllvm -polly-parallel -lgomp -mllvm -polly-vectorizer=stripmine -lm -o main main.c -fopenmp=libomp -march=native -lcrypto
5+
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <stdbool.h>
9+
10+
#include <openssl/md5.h>
11+
12+
#define VEC_SIZE 8
13+
14+
typedef struct Vec
15+
{
16+
double x[VEC_SIZE];
17+
} Vec;
18+
19+
void fill(Vec* in,double val)
20+
{
21+
for(int i=0;i<VEC_SIZE;++i)
22+
{
23+
in->x[i]=val;
24+
}
25+
26+
}
27+
28+
void mul(Vec* r,Vec* a,Vec* b)
29+
{
30+
for(int i=0;i<VEC_SIZE;++i)
31+
{
32+
r->x[i]=a->x[i]*b->x[i];
33+
}
34+
}
35+
36+
void minus(Vec* r,Vec* a,Vec* b)
37+
{
38+
for(int i=0;i<VEC_SIZE;++i)
39+
{
40+
r->x[i]=a->x[i]-b->x[i];
41+
}
42+
43+
}
44+
45+
void add(Vec* r,Vec* a,Vec* b)
46+
{
47+
for(int i=0;i<VEC_SIZE;++i)
48+
{
49+
r->x[i]=a->x[i]+b->x[i];
50+
}
51+
}
52+
53+
unsigned char mbrot8(Vec* cr, double civ)
54+
{
55+
Vec ci,zr,zi,tr,ti,absz;
56+
fill(&ci,civ);
57+
fill(&zr,0.0);
58+
fill(&zi,0.0);
59+
fill(&tr,0.0);
60+
fill(&ti,0.0);
61+
fill(&absz,0.0);
62+
Vec tmp;
63+
64+
for(int i=0;i<10;++i)
65+
{
66+
for(int j=0;j<5;++j)
67+
{
68+
add(&tmp, &zr, &zr);
69+
mul(&tmp, &tmp, &zi);
70+
add(&zi, &tmp, &ci);
71+
72+
minus(&tmp, &tr, &ti);
73+
add(&zr, &tmp, cr);
74+
mul(&tr, &zr, &zr);
75+
mul(&ti, &zi, &zi);
76+
}
77+
78+
add(&absz,&tr,&ti);
79+
unsigned char terminate = true;
80+
for(int k=0;k<VEC_SIZE;++k)
81+
{
82+
if(absz.x[k]<=4.0)
83+
{
84+
terminate=false;//0
85+
break;
86+
}
87+
}
88+
if(terminate)
89+
{
90+
return 0;
91+
}
92+
93+
}
94+
95+
char accu=0;
96+
for(int k=0;k<VEC_SIZE;++k)
97+
{
98+
if(absz.x[k]<=4.0)
99+
{
100+
const unsigned char lhs = 0x80;
101+
accu |= (lhs >> k);
102+
}
103+
104+
}
105+
106+
return accu;
107+
}
108+
109+
double init_xloc(int i,double inv)
110+
{
111+
return ((double)i)*inv-1.5;
112+
113+
}
114+
115+
116+
int main(int argc, char **argv)
117+
{
118+
int n = (argc > 1) ? atoi(argv[1]) : 200;
119+
int size = (n + VEC_SIZE - 1)/VEC_SIZE*VEC_SIZE;
120+
int chunk_size=size/VEC_SIZE;
121+
double inv = 2.0 / ((double)size);
122+
123+
Vec *xloc=(Vec*) malloc(chunk_size*sizeof(Vec));
124+
125+
for(int i=0;i<chunk_size;++i)
126+
{
127+
int offset = i*VEC_SIZE;
128+
for(int j=0;j<VEC_SIZE;++j)
129+
{
130+
xloc[i].x[j]=init_xloc(offset+j, inv);
131+
}
132+
}
133+
printf("P4\n%d %d\n",size,size);
134+
135+
unsigned char* pixels = (unsigned char*)malloc(size*chunk_size*sizeof(unsigned char));
136+
137+
138+
for(int y=0;y<size;++y)
139+
{
140+
double ci = ((double)y)*inv-1.0;
141+
for(int x=0;x<chunk_size;++x)
142+
{
143+
pixels[y*chunk_size+x]=mbrot8(&xloc[x],ci);
144+
}
145+
}
146+
147+
/* printf("{ ");
148+
for(int x=0;x<size*chunk_size;++x)
149+
{
150+
printf("%d, ",pixels[x]);
151+
}// */
152+
unsigned char *output = MD5(pixels, size*chunk_size,NULL);
153+
for(int i=0;i<16;++i)
154+
{
155+
printf("%02x", (unsigned char)output[i]);
156+
}
157+
printf("\n");
158+
//free(output);
159+
return 0;
160+
}

Diff for: bench/algorithm/mandelbrot/1-mffi.c

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
//translated from Zig
2+
//
3+
//gcc -O3 -mno-fma -march=native -Wall main.c
4+
//clang -O3 -Wno-deprecated -mno-fma -mllvm -polly -mllvm -polly-parallel -lgomp -mllvm -polly-vectorizer=stripmine -lm -o main main.c -fopenmp=libomp -march=native -lcrypto
5+
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <stdbool.h>
9+
10+
#include <openssl/md5.h>
11+
12+
#define VEC_SIZE 8
13+
14+
typedef struct Vec
15+
{
16+
double x[VEC_SIZE];
17+
} Vec;
18+
19+
void fill(Vec* in,double val)
20+
{
21+
for(int i=0;i<VEC_SIZE;++i)
22+
{
23+
in->x[i]=val;
24+
}
25+
26+
}
27+
28+
void mul(Vec* r,Vec* a,Vec* b)
29+
{
30+
for(int i=0;i<VEC_SIZE;++i)
31+
{
32+
r->x[i]=a->x[i]*b->x[i];
33+
}
34+
}
35+
36+
void minus(Vec* r,Vec* a,Vec* b)
37+
{
38+
for(int i=0;i<VEC_SIZE;++i)
39+
{
40+
r->x[i]=a->x[i]-b->x[i];
41+
}
42+
43+
}
44+
45+
void add(Vec* r,Vec* a,Vec* b)
46+
{
47+
for(int i=0;i<VEC_SIZE;++i)
48+
{
49+
r->x[i]=a->x[i]+b->x[i];
50+
}
51+
}
52+
53+
unsigned char mbrot8(Vec* cr, double civ)
54+
{
55+
Vec ci,zr,zi,tr,ti,absz;
56+
fill(&ci,civ);
57+
fill(&zr,0.0);
58+
fill(&zi,0.0);
59+
fill(&tr,0.0);
60+
fill(&ti,0.0);
61+
fill(&absz,0.0);
62+
Vec tmp;
63+
64+
for(int i=0;i<10;++i)
65+
{
66+
for(int j=0;j<5;++j)
67+
{
68+
add(&tmp, &zr, &zr);
69+
mul(&tmp, &tmp, &zi);
70+
add(&zi, &tmp, &ci);
71+
72+
minus(&tmp, &tr, &ti);
73+
add(&zr, &tmp, cr);
74+
mul(&tr, &zr, &zr);
75+
mul(&ti, &zi, &zi);
76+
}
77+
78+
add(&absz,&tr,&ti);
79+
unsigned char terminate = true;
80+
for(int k=0;k<VEC_SIZE;++k)
81+
{
82+
if(absz.x[k]<=4.0)
83+
{
84+
terminate=false;//0
85+
break;
86+
}
87+
}
88+
if(terminate)
89+
{
90+
return 0;
91+
}
92+
93+
}
94+
95+
char accu=0;
96+
for(int k=0;k<VEC_SIZE;++k)
97+
{
98+
if(absz.x[k]<=4.0)
99+
{
100+
const unsigned char lhs = 0x80;
101+
accu |= (lhs >> k);
102+
}
103+
104+
}
105+
106+
return accu;
107+
}
108+
109+
double init_xloc(int i,double inv)
110+
{
111+
return ((double)i)*inv-1.5;
112+
113+
}
114+
115+
116+
int main(int argc, char **argv)
117+
{
118+
int n = (argc > 1) ? atoi(argv[1]) : 200;
119+
int size = (n + VEC_SIZE - 1)/VEC_SIZE*VEC_SIZE;
120+
int chunk_size=size/VEC_SIZE;
121+
double inv = 2.0 / ((double)size);
122+
123+
Vec *xloc=(Vec*) malloc(chunk_size*sizeof(Vec));
124+
125+
for(int i=0;i<chunk_size;++i)
126+
{
127+
int offset = i*VEC_SIZE;
128+
for(int j=0;j<VEC_SIZE;++j)
129+
{
130+
xloc[i].x[j]=init_xloc(offset+j, inv);
131+
}
132+
}
133+
printf("P4\n%d %d\n",size,size);
134+
135+
unsigned char* pixels = (unsigned char*)malloc(size*chunk_size*sizeof(unsigned char));
136+
137+
#pragma omp parallel for
138+
for(int y=0;y<size;++y)
139+
{
140+
double ci = ((double)y)*inv-1.0;
141+
for(int x=0;x<chunk_size;++x)
142+
{
143+
pixels[y*chunk_size+x]=mbrot8(&xloc[x],ci);
144+
}
145+
}
146+
147+
/* printf("{ ");
148+
for(int x=0;x<size*chunk_size;++x)
149+
{
150+
printf("%d, ",pixels[x]);
151+
}// */
152+
unsigned char *output = MD5(pixels, size*chunk_size,NULL);
153+
for(int i=0;i<16;++i)
154+
{
155+
printf("%02x", (unsigned char)output[i]);
156+
}
157+
printf("\n");
158+
//free(output);
159+
return 0;
160+
}

Diff for: bench/bench_c_ffi.yaml

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
lang: c
2+
problems:
3+
- name: mandelbrot
4+
source:
5+
- 1-ffi.c
6+
- 1-mffi.c
7+
compiler_version_command:
8+
compiler_version_regex:
9+
runtime_version_parameter:
10+
runtime_version_regex:
11+
source_rename_to: app.c
12+
environments:
13+
- os: linux
14+
compiler: clang
15+
compiler_version_command: clang --version
16+
version: latest
17+
docker:
18+
include: c
19+
build: clang @app_ffi.rsp
20+
after_build:
21+
- mv app out
22+
out_dir: out
23+
run_cmd: app
24+
- os: linux
25+
compiler: gcc
26+
compiler_version_command: gcc --version
27+
version: latest
28+
docker: gcc
29+
include: c
30+
build: gcc @app_ffi.rsp
31+
after_build:
32+
- mv app out
33+
out_dir: out
34+
run_cmd: app
35+
- os: linux
36+
compiler: zigcc
37+
version: latest
38+
docker:
39+
include: c
40+
build: zig cc -pipe -O3 -fomit-frame-pointer -march=native -Wno-deprecated-declarations -mno-fma -o app app.c -lm -lcrypto
41+
after_build:
42+
- mv app out
43+
out_dir: out
44+
run_cmd: app

Diff for: bench/include/c/app_ffi.rsp

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-pipe -O3 -fomit-frame-pointer -march=broadwell -fopenmp -pthread -Wno-deprecated-declarations -mno-fma -o app app.c -lm -lcrypto

0 commit comments

Comments
 (0)