float_parsing.c   [plain text]


#include <dispatch/dispatch.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <math.h>

#define MAXLAPS (512 * 1024)

static void
test(size_t LAPS, char *nums)
{
	uint64_t concurrent_cycles;
	uint64_t serial_cycles;
	char **result_strings;
	char *nums_off;
	double *results;
	size_t i;

	result_strings = calloc(1, sizeof(char *) * LAPS);
	assert(result_strings);

	results = calloc(1, sizeof(double) * LAPS);
	assert(results);

	printf("%zu random floats\n", LAPS);

	i = 0;
	nums_off = nums;
	do {
		result_strings[i] = nums_off;
		do {
			nums_off++;
			assert(*nums_off);
		} while (*nums_off != '\n');
		i++;
		nums_off++;
	} while (i < LAPS);

	for (i = 0; i < LAPS; i++) {
		assert(result_strings[i]);
	}

	concurrent_cycles = dispatch_benchmark(10, ^{
		dispatch_apply(LAPS, dispatch_get_concurrent_queue(0), ^(size_t idx) {
			results[idx] = strtod(result_strings[idx], NULL);
		});
	});

	for (i = 0; i < LAPS; i++) {
		assert(results[i]);
	}

	serial_cycles = dispatch_benchmark(10, ^{
		size_t k = 0;
		do {
			results[k] = strtod(result_strings[k], NULL);
			k++;
		} while (k < LAPS);
	});

	for (i = 0; i < LAPS; i++) {
		assert(results[i]);
	}

	printf(	"\tserial cycles:\t%llu\n"
			"\tapply() cycles:\t%llu\n"
			"\tserial / concurrent: %.2Lf\n",
		serial_cycles, concurrent_cycles,
		(long double)serial_cycles / (long double)concurrent_cycles);

	free(result_strings);
	free(results);
}

int
main(void)
{
	char path[PATH_MAX] = "/tmp/random_floats_XXXXXX";
	struct stat sb;
	double words[1000];
	char buf[1024];
	char *nums;
	int fd, rfd;
	size_t i, j;
	ssize_t r;

	rfd = open("/dev/random", O_RDONLY);
	assert(rfd != -1);

	fd = mkstemp(path);
	assert(fd != -1);

	r = unlink(path);
	assert(r != -1);

	i = 0;
	do {
		r = read(rfd, words, sizeof(words));
		assert(r == sizeof(words));
		for (j = 0; j < 1000; j++) {
			if (isnormal(words[j])) {
				r = write(fd, buf, snprintf(buf, sizeof(buf), "%.20e\n", words[j]));
				assert(r != -1);
				i++;
			}
		}
	} while (i < MAXLAPS);

	r = close(rfd);
	assert(r != -1);

	r = fstat(fd, &sb);
	assert(r != -1);

	nums = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0);
	assert(nums != MAP_FAILED);

	for (i = MAXLAPS; i > 0; i /= 2) {
		test(i, nums);
	}

	r = munmap(nums, sb.st_size);
	assert(r != -1);

	r = close(fd);
	assert(r != -1);

	return 0;
}