shithub: brokentoys

Download patch

ref: 078a88d34b87ffb1333a1ff886a551ad49ca1d79
parent: 51ac274721ac93459bc108b5315b66bb798d2abe
author: rodri <rgl@antares-labs.eu>
date: Sun Apr 27 20:48:59 EDT 2025

image/convolution: parallelize

--- a/image/convolution.c
+++ b/image/convolution.c
@@ -142,12 +142,25 @@
 }
 
 static void
-imgconvolution(Memimage *d, Memimage *s, double *k, int dim)
+mksubrects(Rectangle *sr, int nsr, Rectangle *r)
 {
+	int i, Δy;
+
+	sr[0] = *r;
+	Δy = Dy(sr[0])/nsr;
+	sr[0].max.y = sr[0].min.y + Δy;
+	for(i = 1; i < nsr; i++)
+		sr[i] = rectaddpt(sr[i-1], Pt(0,Δy));
+	if(sr[nsr-1].max.y < r->max.y)
+		sr[nsr-1].max.y = r->max.y;
+}
+
+static void
+subimgconvolution(Memimage *d, Memimage *s, Rectangle *r, double *k, int dim, double denom)
+{
 	double **im;
-	Rectangle imr;
 	Point imc, p, cp;
-	double denom, c;
+	double c;
 	int i;
 
 	im = emalloc(d->nchan*sizeof(double*));
@@ -154,16 +167,12 @@
 	for(i = 0; i < d->nchan; i++)
 		im[i] = emalloc(dim*dim*sizeof(double));
 
-	imr = Rect(0,0,dim,dim);
 	imc = Pt(dim/2, dim/2);
 
-	denom = coeffsum(k, dim);
-	denom = denom == 0? 1: 1/denom;
-
-	for(p.y = s->r.min.y; p.y < s->r.max.y; p.y++)
-	for(p.x = s->r.min.x; p.x < s->r.max.x; p.x++){
-		for(cp.y = imr.min.y; cp.y < imr.max.y; cp.y++)
-		for(cp.x = imr.min.x; cp.x < imr.max.x; cp.x++){
+	for(p.y = r->min.y; p.y < r->max.y; p.y++)
+	for(p.x = r->min.x; p.x < r->max.x; p.x++){
+		for(cp.y = 0; cp.y < dim; cp.y++)
+		for(cp.x = 0; cp.x < dim; cp.x++){
 			for(i = 0; i < d->nchan; i++)
 				im[i][cp.y*dim + cp.x] = sample(s, addpt(p, subpt(cp, imc)), i);
 		}
@@ -178,6 +187,40 @@
 	for(i = 0; i < d->nchan; i++)
 		free(im[i]);
 	free(im);
+}
+
+static void
+imgconvolution(Memimage *d, Memimage *s, double *k, int dim)
+{
+	double denom;
+	Rectangle *subr;
+	char *nprocs;
+	int nproc, i;
+
+	denom = coeffsum(k, dim);
+	denom = denom == 0? 1: 1/denom;
+
+	nprocs = getenv("NPROC");
+	if(nprocs == nil || (nproc = strtoul(nprocs, nil, 10)) < 2)
+		nproc = 1;
+	free(nprocs);
+
+	subr = emalloc(nproc*sizeof(*subr));
+	mksubrects(subr, nproc, &s->r);
+
+	for(i = 0; i < nproc; i++){
+		switch(rfork(RFPROC|RFMEM)){
+		case -1:
+			sysfatal("rfork: %r");
+		case 0:
+			subimgconvolution(d, s, &subr[i], k, dim, denom);
+			exits(nil);
+		}
+	}
+	while(waitpid() != -1)
+		;
+
+	free(subr);
 }
 
 
--