Skip to content
This repository has been archived by the owner on Jan 23, 2018. It is now read-only.

Commit

Permalink
Serial 6: uses sendfile to work in place.
Browse files Browse the repository at this point in the history
No major changes though.
  • Loading branch information
greut committed Dec 6, 2012
1 parent 50b6a73 commit 85a6fef
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 3 deletions.
7 changes: 7 additions & 0 deletions README.md
Expand Up @@ -46,6 +46,13 @@ Built from Serial 4.
It doesn't work in-place anymore and the file is read using `mmap` which cuts
off the loading time of the bitmap entirely.

### Serial 6

Built from Serial 5.

Copy the input file to the output file destination using `sendfile` and then
works in place using `mmap`. No save operations are required.

### OpenMP 0

Built from Serial 4.
Expand Down
6 changes: 6 additions & 0 deletions data/serial6.tsv
@@ -0,0 +1,6 @@
img/100x100@24.bmp 10000 0 0 0 0 0
img/300x300@24.bmp 90000 0.01 0 0 0.01 0
img/1000x1000@24.bmp 1000000 0.13 0.05 0.02 0.06 0
img/2000x2000@24.bmp 4000000 0.54 0.19 0.13 0.22 0
img/4000x4000@24.bmp 16000000 2.22 0.78 0.56 0.87 0.01
img/8000x8000@24.bmp 64000000 8.97 3.1 2.18 3.66 0.03
4 changes: 2 additions & 2 deletions measures.sh
Expand Up @@ -4,7 +4,7 @@ TMP=_.bmp
# the very max
export OMP_NUM_THREADS=8

for i in `seq 0 5`; do
for i in `seq 0 6`; do
echo Serial $i
echo "---------"
d=src/serial$i
Expand All @@ -13,7 +13,7 @@ for i in `seq 0 5`; do
rm -f $tsv
for img in $IMAGES; do
echo " $img"
time `$d/fisheye img/$img $TMP >> $sv`
time `$d/fisheye img/$img $TMP >> $tsv`
rm -f $TMP
echo ""
echo ""
Expand Down
4 changes: 4 additions & 0 deletions plot.sh
Expand Up @@ -18,6 +18,7 @@ gnuplot <<EOF
"$data/serial3.tsv" u (\$2/$f):(\$5+\$6) title "serial 3" with linespoints, \\
"$data/serial4.tsv" u (\$2/$f):(\$5+\$6) title "serial 4" with linespoints, \\
"$data/serial5.tsv" u (\$2/$f):(\$5+\$6) title "serial 5" with linespoints, \\
"$data/serial6.tsv" u (\$2/$f):(\$5+\$6) title "serial 6" with linespoints, \\
"$data/openmp0.tsv" u (\$2/$f):(\$5+\$6) title "openmp 0 ($cores)" with linespoints, \\
"$data/openmp1.tsv" u (\$2/$f):(\$5+\$6) title "openmp 1 ($cores)" with linespoints
EOF
Expand All @@ -37,6 +38,7 @@ gnuplot <<EOF
"$data/serial3.tsv" u (\$2/$f):(\$5+\$6) every ::2 title "serial 3" with linespoints, \\
"$data/serial4.tsv" u (\$2/$f):(\$5+\$6) every ::2 title "serial 4" with linespoints, \\
"$data/serial5.tsv" u (\$2/$f):(\$5+\$6) every ::2 title "serial 5" with linespoints, \\
"$data/serial6.tsv" u (\$2/$f):(\$5+\$6) every ::2 title "serial 6" with linespoints, \\
"$data/openmp0.tsv" u (\$2/$f):(\$5+\$6) every ::2 title "openmp 0 ($cores)" with linespoints, \\
"$data/openmp1.tsv" u (\$2/$f):(\$5+\$6) every ::2 title "openmp 1 ($cores)" with linespoints
EOF
Expand All @@ -55,6 +57,7 @@ gnuplot <<EOF
"$data/serial3.tsv" u (\$2/$f):3 title "serial 3" with linespoints, \\
"$data/serial4.tsv" u (\$2/$f):3 title "serial 4" with linespoints, \\
"$data/serial5.tsv" u (\$2/$f):3 title "serial 5" with linespoints, \\
"$data/serial6.tsv" u (\$2/$f):3 title "serial 6" with linespoints, \\
"$data/openmp0.tsv" u (\$2/$f):3 title "openmp 0 ($cores)" with linespoints, \\
"$data/openmp1.tsv" u (\$2/$f):3 title "openmp 1 ($cores)" with linespoints
EOF
Expand All @@ -74,6 +77,7 @@ gnuplot <<EOF
"$data/serial3.tsv" u (\$2/$f):3 every ::2 title "serial 3" with linespoints, \\
"$data/serial4.tsv" u (\$2/$f):3 every ::2 title "serial 4" with linespoints, \\
"$data/serial5.tsv" u (\$2/$f):3 every ::2 title "serial 5" with linespoints, \\
"$data/serial6.tsv" u (\$2/$f):3 every ::2 title "serial 6" with linespoints, \\
"$data/openmp0.tsv" u (\$2/$f):3 every ::2 title "openmp 0 ($cores)" with linespoints, \\
"$data/openmp1.tsv" u (\$2/$f):3 every ::2 title "openmp 1 ($cores)" with linespoints
EOF
2 changes: 1 addition & 1 deletion src/serial5/fisheye.cc
Expand Up @@ -251,7 +251,7 @@ main(int argc, const char** argv) {
clock_t t2 = clock();
fisheye_from_square_half_mask(src, dst, mask, mask_width);
clock_t t3 = clock();
clock_t saved = saveBitmap(argv[2], dst);
int saved = saveBitmap(argv[2], dst);
free(mask);
destroyBitmap(src);
destroyBitmap(dst);
Expand Down
7 changes: 7 additions & 0 deletions src/serial6/Makefile
@@ -0,0 +1,7 @@
CC=g++
CPPFLAGS = -g -O0 -W -Wall -pedantic -std=c++0x -I../libs
LDFLAGS = -lm
fisheye: fisheye.o ../libs/lspbmp.o ../libs/magnify.o

clean:
rm -f fisheye fisheye.o ../lib/lspbmp.o ../libs/magnify.o
223 changes: 223 additions & 0 deletions src/serial6/fisheye.cc
@@ -0,0 +1,223 @@
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "lspbmp.h"
#include "magnify.h"

#define COLORS 3

void fisheye_square_half_mask(double * mask, int width, double r, double m) {
geometry_t g = {
(int) ceil(2. * r),
(int) ceil(2. * r),
{r, r}
};
point_t *c = point_new(0., 0.), *nc;
polar_t *p, *np;
int x, y, x2, y2, ycol, xcol;
double dx, dy,
shift = r - width;
for (y=0; y < width; y++) {
c->y = (double) y + shift;
ycol = y * width << 1;
y2 = y << 1;
for (x = y; x < width; x++) {
c->x = (double) x + shift;
p = geometry_polar_from_point(&g, c);
if (p->r < r) {
np = unmagnify(p, r, m);
nc = geometry_point_from_polar(&g, np);
dx = nc->x - c->x; // nc->x = x + dx
dy = nc->y - c->y; // nc->y = y + dy

free(nc);
free(np);
xcol = x * width << 1;
x2 = x << 1;

mask[ycol + x2] = dx;
mask[ycol + x2 + 1] = dy;
if (x != y) {
mask[xcol + y2] = dy;
mask[xcol + y2 + 1] = dx;
}
}
free(p);
}
}
free(c);
}

void
fisheye_inplace_sub(Bitmap* img, const point_t *c, const double* dv) {
double dx, dy, idx, idy, r0, g0, b0, r1, g1, b1;
unsigned int nx, ny, mx, my,
x = c->x * COLORS,
width = img->width * COLORS;
unsigned char *data0, *data1, *to, r, g, b;
double cx = c->x + dv[0],
cy = c->y + dv[1];

nx = floor(cx);
ny = floor(cy);
mx = ceil(cx);
my = ceil(cy);
dx = cx - nx;
dy = cy - ny;
idx = 1 - dx;
idy = 1 - dy;
nx *= COLORS;
mx *= COLORS;
// rows
data0 = &(img->data[ny * width]);
data1 = &(img->data[my * width]);
to = &(img->data[(int)(c->y * width)]);
// intermediary points
r0 = idx * data0[nx] + dx * data0[mx + 0];
g0 = idx * data0[nx + 1] + dx * data0[mx + 1];
b0 = idx * data0[nx + 2] + dx * data0[mx + 2];
r1 = idx * data1[nx] + dx * data1[mx + 0];
g1 = idx * data1[nx + 1] + dx * data1[mx + 1];
b1 = idx * data1[nx + 2] + dx * data1[mx + 2];
// final points
r = idy * r0 + dy * r1;
g = idy * g0 + dy * g1;
b = idy * b0 + dy * b1;
to[x] = r;
to[x + 1] = g;
to[x + 2] = b;
}

void
fisheye_inplace_from_square_half_mask(Bitmap* img, double* mask, unsigned int mask_width) {
point_t *c = point_new(0, 0), *r = point_new(0, 0);
unsigned int x, y, x0 = 0, y0 = 0, yy, zero = 0,
width = img->width,
height = img->height,
ycorr = height % 2 ? 0 : 1,
xcorr = width % 2 ? 0 : 1;

double* dv;
if (width / 2 > mask_width) {
x0 = std::max(zero, ((width / 2) - mask_width));
}
if (height / 2 > mask_width) {
y0 = std::max(zero, ((height / 2) - mask_width));
}

for (y = 0; y < mask_width; y++) {
c->y = y + y0;
r->y = width - ycorr - (y + y0);
yy = y * mask_width << 1;
for (x = 0; x < mask_width; x++) {
dv = &(mask[yy + (x << 1)]);
if (dv[0] != 0 || dv[1] != 0) {
// North-West
c->x = x + x0;
fisheye_inplace_sub(img, c, dv);

// North-East
dv[0] = -dv[0];
c->x = width - xcorr - (x + x0);
fisheye_inplace_sub(img, c, dv);

// South-East
dv[1] = -dv[1];
r->x = width - xcorr - (x + x0);
fisheye_inplace_sub(img, r, dv);
dv[0] = -dv[0];

// South-West
r->x = x + x0;
fisheye_inplace_sub(img, r, dv);
dv[1] = -dv[1];
}
}
}

free(c);
free(r);
}

// This function is not portable
int fcopy(const char *from, const char *to) {
unsigned int ifd, ofd;
struct stat buf;
off_t offset = 0;

ifd = open(from, O_RDONLY);
if (ifd == 0) {
fprintf(stderr, "Cannot open %s\n", from);
return 0;
}
fstat(ifd, &buf);
ofd = open(to, O_RDWR|O_CREAT|O_TRUNC, buf.st_mode);
if (ofd == 0) {
fprintf(stderr, "Cannot open %s\n", to);
return 0;
}

sendfile(ofd, ifd, &offset, buf.st_size);

close(ifd);
close(ofd);
return 1;
}

int
main(int argc, const char** argv) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " source dest"<< std::endl;
return 1;
}
clock_t t0 = clock();
if (!fcopy(argv[1], argv[2])) {
std::cerr << "Cannot copy the file" << std::endl;
return 1;
}
Bitmap* img = loadBitmap(argv[2]);
int width = img->width,
height = img->height;
clock_t t1 = clock();
double radius = std::min(height, width) * .45,
magnify_factor = 5.0;
if (argc > 3) {
sscanf(argv[3], "%lf", &radius);
if (radius <= 0) {
std::cerr << "Radius cannot be null or negative" << std::endl;
return 1;
}
}
if (argc > 4) {
sscanf(argv[4], "%lf", &magnify_factor);
if (magnify_factor < 1) {
std::cerr << "Less than 1 magnify lens are not supported" << std::endl;
return 1;
}
}
unsigned int mask_width = ceil(std::min(std::min(width, height)/2., radius));
double *mask = (double *) calloc(
sizeof(double),
mask_width * mask_width << 1);
fisheye_square_half_mask(mask, mask_width, radius, magnify_factor);
clock_t t2 = clock();
fisheye_inplace_from_square_half_mask(img, mask, mask_width);
clock_t t3 = clock();
free(mask);
destroyBitmap(img);
clock_t t4 = clock();

std::cout << argv[1] << "\t";
std::cout << width * height << "\t";
std::cout << double(t4-t0)/CLOCKS_PER_SEC << "\t";
std::cout << double(t1-t0)/CLOCKS_PER_SEC << "\t";
std::cout << double(t2-t1)/CLOCKS_PER_SEC << "\t";
std::cout << double(t3-t2)/CLOCKS_PER_SEC << "\t";
std::cout << double(t4-t3)/CLOCKS_PER_SEC << std::endl;
return 0;
}

0 comments on commit 85a6fef

Please sign in to comment.