Commit d755b894 authored by Philip Carns's avatar Philip Carns
Browse files

initial commit

- first wrappers implemented, skeleton for test program
parents
#
# Output dist version
#
.phony: distversion
distversion:
@echo $(VERSION)
#
# Easy way to build unit tests without running them
#
.phony: tests
tests: $(check_PROGRAMS)
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS =
bin_SCRIPTS =
noinst_LIBRARIES =
noinst_PROGRAMS =
lib_LIBRARIES =
noinst_HEADERS =
TESTS =
XFAIL_TESTS =
check_PROGRAMS =
EXTRA_PROGRAMS =
CLEANFILES = $(bin_SCRIPTS)
MAINTAINERCLEANFILES =
EXTRA_DIST =
BUILT_SOURCES =
include_HEADERS = include/abt-io.h
EXTRA_DIST += \
prepare.sh
AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CFLAGS =
AM_LIBS =
AM_CXXFLAGS = $(AM_CFLAGS)
lib_LIBRARIES += src/libabt-io.a
src_libabt_io_a_SOURCES =
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = maint/abt-io.pc
include Make.rules
include $(top_srcdir)/src/Makefile.subdir
include $(top_srcdir)/examples/Makefile.subdir
# abt-io
abt-io is a library that provides Argobots bindings to common POSIX I/O
functions.
## Dependencies
* argobots (git://git.mcs.anl.gov/argo/argobots.git)
* abt-snoozer (https://xgitlab.cels.anl.gov/sds/abt-snoozer)
## Building
Example configuration:
../configure --prefix=/home/pcarns/working/install \
PKG_CONFIG_PATH=/home/pcarns/working/install/lib/pkgconfig \
CFLAGS="-g -Wall"
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.67])
AC_INIT([abt-io], [0.1], [],[],[])
AC_CANONICAL_TARGET
AC_CANONICAL_SYSTEM
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([foreign subdir-objects -Wall])
# we should remove this soon, only needed for automake 1.10 and older
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_SRCDIR([README.md])
AC_CONFIG_HEADERS([abt-io-config.h])
# Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CXX
AC_PROG_CXXCPP
AC_PROG_RANLIB
AC_PROG_MKDIR_P
AC_REQUIRE_CPP
AC_CHECK_SIZEOF([long int])
dnl
dnl Verify pkg-config
dnl
PKG_PROG_PKG_CONFIG
PKG_CONFIG="pkg-config --static"
PKG_CHECK_MODULES_STATIC([ARGOBOTS],[argobots],[],
[AC_MSG_ERROR([Could not find working argobots installation!])])
LIBS="$ARGOBOTS_LIBS $LIBS"
CPPFLAGS="$ARGOBOTS_CFLAGS $CPPFLAGS"
CFLAGS="$ARGOBOTS_CFLAGS $CFLAGS"
PKG_CHECK_MODULES_STATIC([ABT_SNOOZER],[abt-snoozer],[],
[AC_MSG_ERROR([Could not find working abt-snoozer installation!])])
LIBS="$ABT_SNOOZER_LIBS $LIBS"
CPPFLAGS="$ABT_SNOOZER_CFLAGS $CPPFLAGS"
CFLAGS="$ABT_SNOOZER_CFLAGS $CFLAGS"
AC_CONFIG_FILES([Makefile maint/abt-io.pc])
AC_OUTPUT
bin_PROGRAMS += examples/concurrent-write-bench
examples_concurrent_write_bench_SOURCES = \
examples/concurrent-write-bench.c \
examples_client_LDADD = src/libabt-io.a
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <sys/time.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/* This is a simple benchmark that measures the
* streaming, concurrent, sequentially-issued write throughput for a
* specified number of concurrent operations. It includes an abt-io version and
* a pthread version.
*
* Both tests use O_DIRECT and O_SYNC if available.
*/
/* abt data types and fn prototypes */
struct write_abt_arg
{
double start_time;
size_t size;
// struct fbr_mutex *mutex;
off_t *next_offset;
int fd;
double duration;
};
static void write_abt_bench(void *_arg);
static void abt_bench(unsigned int concurrency, size_t size,
double duration, const char* filename, unsigned int* ops_done, double *seconds);
/* pthread data types and fn prototypes */
struct write_pthread_arg
{
double start_time;
size_t size;
pthread_mutex_t *mutex;
off_t *next_offset;
int fd;
double duration;
};
static void* write_pthread_bench(void *_arg);
static void pthread_bench(unsigned int concurrency, size_t size,
double duration, const char* filename, unsigned int* ops_done, double *seconds);
static double wtime(void);
int main(int argc, char **argv)
{
int ret;
unsigned abt_ops_done, pthread_ops_done;
double abt_seconds, pthread_seconds;
size_t size;
unsigned int concurrency;
double duration;
if(argc != 5)
{
fprintf(stderr, "Usage: concurrent-write-bench <write_size> <concurrency> <duration> <file>\n");
return(-1);
}
ret = sscanf(argv[1], "%zu", &size);
if(ret != 1)
{
fprintf(stderr, "Usage: concurrent-write-bench <write_size> <concurrency> <duration> <file>\n");
return(-1);
}
ret = sscanf(argv[2], "%u", &concurrency);
if(ret != 1)
{
fprintf(stderr, "Usage: concurrent-write-bench <write_size> <concurrency> <duration> <file>\n");
return(-1);
}
ret = sscanf(argv[3], "%lf", &duration);
if(ret != 1)
{
fprintf(stderr, "Usage: concurrent-write-bench <write_size> <concurrency> <duration> <file>\n");
return(-1);
}
/* run benchmarks */
printf("# Running ABT benchmark...\n");
abt_bench(concurrency, size, duration, argv[4], &abt_ops_done, &abt_seconds);
printf("# ...abt benchmark done.\n");
sleep(1);
printf("# Running pthread benchmark...\n");
pthread_bench(concurrency, size, duration, argv[4], &pthread_ops_done, &pthread_seconds);
printf("# ...pthread benchmark done.\n");
/* output */
printf("#<type>\t<concurrency>\t<write_size>\t<ops>\t<seconds>\t<MiB/s>\n");
printf("abt\t%u\t%zu\t%u\t%f\t%f\n",
concurrency, size, abt_ops_done, abt_seconds,
((((double)size*(double)abt_ops_done))/abt_seconds)/(1024.0*1024.0));
printf("pthread\t%u\t%zu\t%u\t%f\t%f\n",
concurrency, size, pthread_ops_done, pthread_seconds,
((((double)size*(double)pthread_ops_done))/pthread_seconds)/(1024.0*1024.0));
return(0);
}
static void abt_bench(unsigned int concurrency, size_t size, double duration,
const char *filename, unsigned int* ops_done, double *seconds)
{
#if 0
fbr_id_t *id_array = NULL;
struct fbr_context context;
struct fbr_mutex mutex;
struct write_fbr_arg arg;
off_t next_offset = 0;
int ret;
double end;
int i;
char fbr_name[128];
arg.fd = open(filename, O_WRONLY|O_CREAT|O_DIRECT|O_SYNC, S_IWUSR|S_IRUSR);
if(!arg.fd)
{
perror("open");
assert(0);
}
id_array = malloc(concurrency * sizeof(*id_array));
assert(id_array);
fbr_init(&context, EV_DEFAULT);
fbr_eio_init();
eio_set_min_parallel(concurrency);
fbr_mutex_init(&context, &mutex);
arg.mutex = &mutex;
arg.size = size;
arg.next_offset = &next_offset;
arg.duration = duration;
for(i=0; i<concurrency; i++)
{
sprintf(fbr_name, "write_fbr_%d", i);
id_array[i] = fbr_create(&context, fbr_name, write_fbr_bench, &arg, 0);
assert(!fbr_id_isnull(id_array[i]));
}
arg.start_time = wtime();
for(i=0; i<concurrency; i++)
{
ret = fbr_transfer(&context, id_array[i]);
assert(ret == 0);
}
ev_run(EV_DEFAULT, 0);
end = wtime();
*seconds = end-arg.start_time;
*ops_done = next_offset/size;
fbr_mutex_destroy(&context, &mutex);
fbr_destroy(&context);
free(id_array);
close(arg.fd);
unlink(filename);
return;
#endif
}
static void pthread_bench(unsigned int concurrency, size_t size, double duration,
const char *filename, unsigned int* ops_done, double *seconds)
{
pthread_t *id_array = NULL;
pthread_mutex_t mutex;
struct write_pthread_arg arg;
off_t next_offset = 0;
int ret;
double end;
int i;
arg.fd = open(filename, O_WRONLY|O_CREAT|O_DIRECT|O_SYNC, S_IWUSR|S_IRUSR);
if(!arg.fd)
{
perror("open");
assert(0);
}
id_array = malloc(concurrency * sizeof(*id_array));
assert(id_array);
pthread_mutex_init(&mutex, NULL);
arg.mutex = &mutex;
arg.size = size;
arg.next_offset = &next_offset;
arg.duration = duration;
arg.start_time = wtime();
for(i=0; i<concurrency; i++)
{
ret = pthread_create(&id_array[i], NULL, write_pthread_bench, &arg);
assert(ret == 0);
}
for(i=0; i<concurrency; i++)
{
ret = pthread_join(id_array[i], NULL);
assert(ret == 0);
}
end = wtime();
*seconds = end-arg.start_time;
*ops_done = next_offset/size;
pthread_mutex_destroy(&mutex);
free(id_array);
close(arg.fd);
unlink(filename);
return;
}
static void write_abt_bench(void *_arg)
{
#if 0
struct write_fbr_arg* arg = _arg;
off_t my_offset;
void *buffer;
size_t ret;
ret = posix_memalign(&buffer, 4096, arg->size);
assert(ret == 0);
memset(buffer, 0, arg->size);
double now = wtime();
while((now-arg->start_time) < arg->duration)
{
fbr_mutex_lock(FBR_A_ arg->mutex);
my_offset = *arg->next_offset;
(*arg->next_offset) += arg->size;
fbr_mutex_unlock(FBR_A_ arg->mutex);
ret = fbr_eio_write(FBR_A_ arg->fd, buffer, arg->size, my_offset, 0);
assert(ret == arg->size);
now = wtime();
}
#endif
return;
}
static void *write_pthread_bench(void *_arg)
{
struct write_pthread_arg* arg = _arg;
off_t my_offset;
void *buffer;
size_t ret;
ret = posix_memalign(&buffer, 4096, arg->size);
assert(ret == 0);
memset(buffer, 0, arg->size);
double now = wtime();
while((now-arg->start_time) < arg->duration)
{
pthread_mutex_lock(arg->mutex);
my_offset = *arg->next_offset;
(*arg->next_offset) += arg->size;
pthread_mutex_unlock(arg->mutex);
ret = pwrite(arg->fd, buffer, arg->size, my_offset);
assert(ret == arg->size);
now = wtime();
}
return(NULL);
}
static double wtime(void)
{
struct timeval t;
gettimeofday(&t, NULL);
return((double)t.tv_sec + (double)t.tv_usec / 1000000.0);
}
/*
* (C) 2015 The University of Chicago
*
* See COPYRIGHT in top-level directory.
*/
#ifndef __ABT_IO
#define __ABT_IO
#ifdef __cplusplus
extern "C" {
#endif
#include <abt.h>
#include <sys/types.h>
struct abt_io_instance;
typedef struct abt_io_instance* abt_io_instance_id;
#define ABT_IO_INSTANCE_NULL ((abt_io_instance_id)NULL)
/**
* Initializes abt_io library.
* @param [in] progress_pool Argobots pool to drive I/O
* @returns abt_io instance id on success, NULL upon error
*/
abt_io_instance_id abt_io_init(ABT_pool progress_pool);
/**
* Shuts down abt_io library and its underlying resources
* @param [in] aid Margo instance
*/
void abt_io_finalize(abt_io_instance_id aid);
/**
* wrapper for open()
*/
int abt_io_open(abt_io_instance_id aid, const char* pathname, int flags, mode_t mode);
/**
* wrapper for pwrite()
*/
ssize_t abt_io_pwrite(abt_io_instance_id aid, int fd, const void *buf, size_t count,
off_t offset);
#ifdef __cplusplus
}
#endif
#endif /* __ABT_IO */
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 1 (pkg-config-0.24)
#
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
# ----------------------------------
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
fi
if test -n "$PKG_CONFIG"; then
_pkg_min_version=m4_default([$1], [0.9.0])
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
PKG_CONFIG=""
fi
fi[]dnl
])# PKG_PROG_PKG_CONFIG
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# Check to see whether a particular set of modules exists. Similar
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
#
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
# only at the first occurence in configure.ac, so if the first place
# it's called might be skipped (such as if it is within an "if", you
# have to call PKG_CHECK_EXISTS manually
# --------------------------------------------------------------
AC_DEFUN([PKG_CHECK_EXISTS],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
if test -n "$PKG_CONFIG" && \
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
m4_default([$2], [:])
m4_ifvaln([$3], [else
$3])dnl
fi])
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
# ---------------------------------------------
m4_define([_PKG_CONFIG],
[if test -n "$$1"; then
pkg_cv_[]$1="$$1"
elif test -n "$PKG_CONFIG"; then
PKG_CHECK_EXISTS([$3],
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes ],
[pkg_failed=yes])
else
pkg_failed=untried
fi[]dnl
])# _PKG_CONFIG
# _PKG_SHORT_ERRORS_SUPPORTED
# -----------------------------
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi[]dnl
])# _PKG_SHORT_ERRORS_SUPPORTED
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
# [ACTION-IF-NOT-FOUND])
#
#
# Note that if there is a possibility the first call to
# PKG_CHECK_MODULES might not happen, you should be sure to include an
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
#
#
# --------------------------------------------------------------
AC_DEFUN([PKG_CHECK_MODULES],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no
AC_MSG_CHECKING([for $1])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
m4_default([$4], [AC_MSG_ERROR(
[Package requirements ($2) were not met:
$$1_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
_PKG_TEXT])[]dnl
])
elif test $pkg_failed = untried; then
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
_PKG_TEXT
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
])
else
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS