Add basic performance and correct test.

This commit is contained in:
Zhang Xianyi 2015-04-17 00:25:33 -05:00
parent 6a12d8658b
commit 2ac453aeba
12 changed files with 1199 additions and 1 deletions

View File

@ -15,6 +15,7 @@ set (OpenVML_FUNC_PREFIX "")
set (OpenVML_FUNC_SUFFIX "")
option(BUILD_SINGLE_THREAD "Only build the single thread" ON)
option(BUILD_OpenVML_TEST "Build Test" ON)
#####################################################
@ -86,6 +87,9 @@ set_target_properties(${OpenVML_LIBNAME}_static PROPERTIES OUTPUT_NAME ${OpenVML
set_target_properties(${OpenVML_LIBNAME}_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
set_target_properties(${OpenVML_LIBNAME} PROPERTIES CLEAN_DIRECT_OUTPUT 1)
target_link_libraries(${OpenVML_LIBNAME} m)
target_link_libraries(${OpenVML_LIBNAME}_static m)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set_target_properties(${OpenVML_LIBNAME} PROPERTIES
@ -111,3 +115,11 @@ install(FILES ${PROJECT_BINARY_DIR}/include/openvml_config.h DESTINATION include
install(FILES ${PROJECT_SOURCE_DIR}/include/openvml.h DESTINATION include)
install(FILES ${PROJECT_SOURCE_DIR}/include/openvml_common.h DESTINATION include)
#test
if(BUILD_OpenVML_TEST)
add_subdirectory(reference)
enable_testing()
add_subdirectory(test)
endif(BUILD_OpenVML_TEST)

View File

@ -35,11 +35,25 @@ extern "C" {
OPENVML_EXPORT void OpenVML_FUNCNAME(vsAdd)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vdAdd)(VML_INT n, const double * a, const double * b, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vcAdd)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vzAdd)(VML_INT n, const double * a, const double * b, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vsSub)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vdSub)(VML_INT n, const double * a, const double * b, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vcSub)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vzSub)(VML_INT n, const double * a, const double * b, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vsPow)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vdPow)(VML_INT n, const double * a, const double * b, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vsExp)(VML_INT n, const float * a, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vdExp)(VML_INT n, const double * a, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vsTanh)(VML_INT n, const float * a, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME(vdTanh)(VML_INT n, const double * a, double * y);
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -0,0 +1,54 @@
/* * Copyright (c) 2014, 2015 Zhang Xianyi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _OPENVML_REFERENCE_H_
#define _OPENVML_REFERENCE_H_
#include "openvml_export.h"
#include "openvml_common.h"
#define OpenVML_FUNCNAME_REF(x) x##_ref
#ifdef __cplusplus
extern "C" {
#endif
OPENVML_EXPORT void OpenVML_FUNCNAME_REF(vsAdd)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME_REF(vdAdd)(VML_INT n, const double * a, const double * b, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME_REF(vcAdd)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME_REF(vzAdd)(VML_INT n, const double * a, const double * b, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME_REF(vsSub)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME_REF(vdSub)(VML_INT n, const double * a, const double * b, double * y);
OPENVML_EXPORT void OpenVML_FUNCNAME_REF(vcSub)(VML_INT n, const float * a, const float * b, float * y);
OPENVML_EXPORT void OpenVML_FUNCNAME_REF(vzSub)(VML_INT n, const double * a, const double * b, double * y);
#ifdef __cplusplus
}
#endif
#endif

7
reference/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
set(OpenVML_REF_SRC
vadd.c
)
add_library(${OpenVML_LIBNAME}_ref SHARED ${OpenVML_REF_SRC})
target_link_libraries(${OpenVML_LIBNAME}_ref m)

72
reference/vadd.c Normal file
View File

@ -0,0 +1,72 @@
/* * Copyright (c) 2014, 2015 Zhang Xianyi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <openvml_reference.h>
void OpenVML_FUNCNAME_REF(vsAdd)(VML_INT n, const float * a, const float * b, float *y)
{
if (n<=0) return;
if (a==NULL || b==NULL || y==NULL) return;
VML_INT i;
for(i=0; i<n; i++) {
y[i]=a[i]+b[i];
}
}
void OpenVML_FUNCNAME_REF(vdAdd)(VML_INT n, const double * a, const double * b, double *y)
{
if (n<=0) return;
if (a==NULL || b==NULL || y==NULL) return;
VML_INT i;
for(i=0; i<n; i++) {
y[i]=a[i]+b[i];
}
}
void OpenVML_FUNCNAME_REF(vcAdd)(VML_INT n, const float * a, const float * b, float *y)
{
if (n<=0) return;
if (a==NULL || b==NULL || y==NULL) return;
VML_INT i;
for(i=0; i<2*n; i++) {
y[i]=a[i]+b[i];
}
}
void OpenVML_FUNCNAME_REF(vzAdd)(VML_INT n, const double * a, const double * b, double *y)
{
if (n<=0) return;
if (a==NULL || b==NULL || y==NULL) return;
VML_INT i;
for(i=0; i<2*n; i++) {
y[i]=a[i]+b[i];
}
}

15
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,15 @@
set(OpenVML_TESTSRC
vml_test.c
vml_util.c
timer.c
test_add.c
)
set(OpenVML_TEST_NAME run_vml_test)
add_executable(${OpenVML_TEST_NAME} ${OpenVML_TESTSRC})
target_link_libraries(${OpenVML_TEST_NAME} ${OpenVML_LIBNAME})
target_link_libraries(${OpenVML_TEST_NAME} ${OpenVML_LIBNAME}_ref)
add_test(${OpenVML_TEST_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${OpenVML_TEST_NAME})

463
test/ctest.h Normal file
View File

@ -0,0 +1,463 @@
/* Copyright 2011,2012 Bas van den Berg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CTEST_H
#define CTEST_H
typedef void (*SetupFunc)(void*);
typedef void (*TearDownFunc)(void*);
struct ctest {
const char* ssname; // suite name
const char* ttname; // test name
void (*run)();
int skip;
void* data;
SetupFunc setup;
TearDownFunc teardown;
unsigned int magic;
};
#define __FNAME(sname, tname) __ctest_##sname##_##tname##_run
#define __TNAME(sname, tname) __ctest_##sname##_##tname
#define __CTEST_MAGIC (0xdeadbeef)
#ifdef __APPLE__
#define __Test_Section __attribute__ ((unused,section ("__DATA, .ctest")))
#else
#define __Test_Section __attribute__ ((unused,section (".ctest")))
#endif
#define __CTEST_STRUCT(sname, tname, _skip, __data, __setup, __teardown) \
struct ctest __TNAME(sname, tname) __Test_Section = { \
.ssname=#sname, \
.ttname=#tname, \
.run = __FNAME(sname, tname), \
.skip = _skip, \
.data = __data, \
.setup = (SetupFunc)__setup,\
.teardown = (TearDownFunc)__teardown,\
.magic = __CTEST_MAGIC };
#define CTEST_DATA(sname) struct sname##_data
#define CTEST_SETUP(sname) \
void __attribute__ ((weak)) sname##_setup(struct sname##_data* data)
#define CTEST_TEARDOWN(sname) \
void __attribute__ ((weak)) sname##_teardown(struct sname##_data* data)
#define __CTEST_INTERNAL(sname, tname, _skip) \
void __FNAME(sname, tname)(); \
__CTEST_STRUCT(sname, tname, _skip, NULL, NULL, NULL) \
void __FNAME(sname, tname)()
#ifdef __APPLE__
#define SETUP_FNAME(sname) NULL
#define TEARDOWN_FNAME(sname) NULL
#else
#define SETUP_FNAME(sname) sname##_setup
#define TEARDOWN_FNAME(sname) sname##_teardown
#endif
#define __CTEST2_INTERNAL(sname, tname, _skip) \
static struct sname##_data __ctest_##sname##_data; \
CTEST_SETUP(sname); \
CTEST_TEARDOWN(sname); \
void __FNAME(sname, tname)(struct sname##_data* data); \
__CTEST_STRUCT(sname, tname, _skip, &__ctest_##sname##_data, SETUP_FNAME(sname), TEARDOWN_FNAME(sname)) \
void __FNAME(sname, tname)(struct sname##_data* data)
void CTEST_LOG(char *fmt, ...);
void CTEST_ERR(char *fmt, ...); // doesn't return
#define CTEST(sname, tname) __CTEST_INTERNAL(sname, tname, 0)
#define CTEST_SKIP(sname, tname) __CTEST_INTERNAL(sname, tname, 1)
#define CTEST2(sname, tname) __CTEST2_INTERNAL(sname, tname, 0)
#define CTEST2_SKIP(sname, tname) __CTEST2_INTERNAL(sname, tname, 1)
void assert_str(const char* exp, const char* real, const char* caller, int line);
#define ASSERT_STR(exp, real) assert_str(exp, real, __FILE__, __LINE__)
void assert_data(const unsigned char* exp, int expsize,
const unsigned char* real, int realsize,
const char* caller, int line);
#define ASSERT_DATA(exp, expsize, real, realsize) \
assert_data(exp, expsize, real, realsize, __FILE__, __LINE__)
void assert_equal(long exp, long real, const char* caller, int line);
#define ASSERT_EQUAL(exp, real) assert_equal(exp, real, __FILE__, __LINE__)
void assert_not_equal(long exp, long real, const char* caller, int line);
#define ASSERT_NOT_EQUAL(exp, real) assert_not_equal(exp, real, __FILE__, __LINE__)
void assert_null(void* real, const char* caller, int line);
#define ASSERT_NULL(real) assert_null((void*)real, __FILE__, __LINE__)
void assert_not_null(const void* real, const char* caller, int line);
#define ASSERT_NOT_NULL(real) assert_not_null(real, __FILE__, __LINE__)
void assert_true(int real, const char* caller, int line);
#define ASSERT_TRUE(real) assert_true(real, __FILE__, __LINE__)
void assert_false(int real, const char* caller, int line);
#define ASSERT_FALSE(real) assert_false(real, __FILE__, __LINE__)
void assert_fail(const char* caller, int line);
#define ASSERT_FAIL() assert_fail(__FILE__, __LINE__)
#ifdef CTEST_MAIN
#include <setjmp.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <inttypes.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef __APPLE__
#include <dlfcn.h>
#endif
//#define COLOR_OK
static size_t ctest_errorsize;
static char* ctest_errormsg;
#define MSG_SIZE 8192
static char ctest_errorbuffer[MSG_SIZE];
static jmp_buf ctest_err;
static int color_output = 1;
static const char* suite_name;
static const char* test_name;
typedef int (*filter_func)(struct ctest*);
#define ANSI_BLACK "\033[0;30m"
#define ANSI_RED "\033[0;31m"
#define ANSI_GREEN "\033[0;32m"
#define ANSI_YELLOW "\033[0;33m"
#define ANSI_BLUE "\033[0;34m"
#define ANSI_MAGENTA "\033[0;35m"
#define ANSI_CYAN "\033[0;36m"
#define ANSI_GREY "\033[0;37m"
#define ANSI_DARKGREY "\033[01;30m"
#define ANSI_BRED "\033[01;31m"
#define ANSI_BGREEN "\033[01;32m"
#define ANSI_BYELLOW "\033[01;33m"
#define ANSI_BBLUE "\033[01;34m"
#define ANSI_BMAGENTA "\033[01;35m"
#define ANSI_BCYAN "\033[01;36m"
#define ANSI_WHITE "\033[01;37m"
#define ANSI_NORMAL "\033[0m"
static CTEST(suite, test) { }
static void msg_start(const char* color, const char* title) {
int size;
if (color_output) {
size = snprintf(ctest_errormsg, ctest_errorsize, "%s", color);
ctest_errorsize -= size;
ctest_errormsg += size;
}
size = snprintf(ctest_errormsg, ctest_errorsize, " %s: ", title);
ctest_errorsize -= size;
ctest_errormsg += size;
}
static void msg_end() {
int size;
if (color_output) {
size = snprintf(ctest_errormsg, ctest_errorsize, ANSI_NORMAL);
ctest_errorsize -= size;
ctest_errormsg += size;
}
size = snprintf(ctest_errormsg, ctest_errorsize, "\n");
ctest_errorsize -= size;
ctest_errormsg += size;
}
void CTEST_LOG(char *fmt, ...)
{
va_list argp;
msg_start(ANSI_BLUE, "LOG");
va_start(argp, fmt);
int size = vsnprintf(ctest_errormsg, ctest_errorsize, fmt, argp);
ctest_errorsize -= size;
ctest_errormsg += size;
va_end(argp);
msg_end();
}
void CTEST_ERR(char *fmt, ...)
{
va_list argp;
msg_start(ANSI_YELLOW, "ERR");
va_start(argp, fmt);
int size = vsnprintf(ctest_errormsg, ctest_errorsize, fmt, argp);
ctest_errorsize -= size;
ctest_errormsg += size;
va_end(argp);
msg_end();
longjmp(ctest_err, 1);
}
void assert_str(const char* exp, const char* real, const char* caller, int line) {
if ((exp == NULL && real != NULL) ||
(exp != NULL && real == NULL) ||
(exp && real && strcmp(exp, real) != 0)) {
CTEST_ERR("%s:%d expected '%s', got '%s'", caller, line, exp, real);
}
}
void assert_data(const unsigned char* exp, int expsize,
const unsigned char* real, int realsize,
const char* caller, int line) {
int i;
if (expsize != realsize) {
CTEST_ERR("%s:%d expected %d bytes, got %d", caller, line, expsize, realsize);
}
for (i=0; i<expsize; i++) {
if (exp[i] != real[i]) {
CTEST_ERR("%s:%d expected 0x%02x at offset %d got 0x%02x",
caller, line, exp[i], i, real[i]);
}
}
}
void assert_equal(long exp, long real, const char* caller, int line) {
if (exp != real) {
CTEST_ERR("%s:%d expected %ld, got %ld", caller, line, exp, real);
}
}
void assert_not_equal(long exp, long real, const char* caller, int line) {
if ((exp) == (real)) {
CTEST_ERR("%s:%d should not be %ld", caller, line, real);
}
}
void assert_null(void* real, const char* caller, int line) {
if ((real) != NULL) {
CTEST_ERR("%s:%d should be NULL", caller, line);
}
}
void assert_not_null(const void* real, const char* caller, int line) {
if (real == NULL) {
CTEST_ERR("%s:%d should not be NULL", caller, line);
}
}
void assert_true(int real, const char* caller, int line) {
if ((real) == 0) {
CTEST_ERR("%s:%d should be true", caller, line);
}
}
void assert_false(int real, const char* caller, int line) {
if ((real) != 0) {
CTEST_ERR("%s:%d should be false", caller, line);
}
}
void assert_fail(const char* caller, int line) {
CTEST_ERR("%s:%d shouldn't come here", caller, line);
}
static int suite_all(struct ctest* t) {
return 1;
}
static int suite_filter(struct ctest* t) {
return strncmp(suite_name, t->ssname, strlen(suite_name)) == 0;
}
static int suite_test_filter(struct ctest* t) {
int suit_match, test_match;
suit_match=(strncmp(suite_name, t->ssname, strlen(suite_name)) == 0);
test_match=(strncmp(test_name, t->ttname, strlen(test_name)) == 0);
return (suit_match & test_match);
}
static uint64_t getCurrentTime() {
struct timeval now;
gettimeofday(&now, NULL);
uint64_t now64 = now.tv_sec;
now64 *= 1000000;
now64 += (now.tv_usec);
return now64;
}
static void color_print(const char* color, const char* text) {
if (color_output)
printf("%s%s"ANSI_NORMAL"\n", color, text);
else
printf("%s\n", text);
}
#ifdef __APPLE__
static void *find_symbol(struct ctest *test, const char *fname)
{
size_t len = strlen(test->ssname) + 1 + strlen(fname);
char *symbol_name = (char *) malloc(len + 1);
memset(symbol_name, 0, len + 1);
snprintf(symbol_name, len + 1, "%s_%s", test->ssname, fname);
//fprintf(stderr, ">>>> dlsym: loading %s\n", symbol_name);
void *symbol = dlsym(RTLD_DEFAULT, symbol_name);
if (!symbol) {
//fprintf(stderr, ">>>> ERROR: %s\n", dlerror());
}
// returns NULL on error
free(symbol_name);
return symbol;
}
#endif
#ifdef CTEST_SEGFAULT
#include <signal.h>
static void sighandler(int signum)
{
char msg[128];
sprintf(msg, "[SIGNAL %d: %s]", signum, sys_siglist[signum]);
color_print(ANSI_BRED, msg);
fflush(stdout);
/* "Unregister" the signal handler and send the signal back to the process
* so it can terminate as expected */
signal(signum, SIG_DFL);
kill(getpid(), signum);
}
#endif
int ctest_main(int argc, char *argv[])
{
static int total = 0;
static int num_ok = 0;
static int num_fail = 0;
static int num_skip = 0;
static int index = 1;
static filter_func filter = suite_all;
#ifdef CTEST_SEGFAULT
signal(SIGSEGV, sighandler);
#endif
if (argc == 2) {
suite_name = argv[1];
filter = suite_filter;
}
if (argc == 3) {
suite_name = argv[1];
test_name = argv[2];
filter = suite_test_filter;
}
color_output = isatty(1);
uint64_t t1 = getCurrentTime();
struct ctest* ctest_begin = &__TNAME(suite, test);
struct ctest* ctest_end = &__TNAME(suite, test);
// find begin and end of section by comparing magics
while (1) {
struct ctest* t = ctest_begin-1;
if (t->magic != __CTEST_MAGIC) break;
ctest_begin--;
}
while (1) {
struct ctest* t = ctest_end+1;
if (t->magic != __CTEST_MAGIC) break;
ctest_end++;
}
ctest_end++; // end after last one
static struct ctest* test;
for (test = ctest_begin; test != ctest_end; test++) {
if (test == &__ctest_suite_test) continue;
if (filter(test)) total++;
}
for (test = ctest_begin; test != ctest_end; test++) {
if (test == &__ctest_suite_test) continue;
if (filter(test)) {
ctest_errorbuffer[0] = 0;
ctest_errorsize = MSG_SIZE-1;
ctest_errormsg = ctest_errorbuffer;
printf("TEST %d/%d %s:%s ", index, total, test->ssname, test->ttname);
fflush(stdout);
if (test->skip) {
color_print(ANSI_BYELLOW, "[SKIPPED]");
num_skip++;
} else {
int result = setjmp(ctest_err);
if (result == 0) {
#ifdef __APPLE__
if (!test->setup) {
test->setup = find_symbol(test, "setup");
}
if (!test->teardown) {
test->teardown = find_symbol(test, "teardown");
}
#endif
if (test->setup) test->setup(test->data);
if (test->data)
test->run(test->data);
else
test->run();
if (test->teardown) test->teardown(test->data);
// if we got here it's ok
#ifdef COLOR_OK
color_print(ANSI_BGREEN, "[OK]");
#else
printf("[OK]\n");
#endif
num_ok++;
} else {
color_print(ANSI_BRED, "[FAIL]");
num_fail++;
}
if (ctest_errorsize != MSG_SIZE-1) printf("%s", ctest_errorbuffer);
}
index++;
}
}
uint64_t t2 = getCurrentTime();
const char* color = (num_fail) ? ANSI_BRED : ANSI_GREEN;
char results[80];
sprintf(results, "RESULTS: %d tests (%d ok, %d failed, %d skipped) ran in %"PRIu64" ms", total, num_ok, num_fail, num_skip, (t2 - t1)/1000);
color_print(color, results);
return num_fail;
}
#endif
#endif

38
test/test_add.c Normal file
View File

@ -0,0 +1,38 @@
#include "vml_test.h"
#include <stdio.h>
#include <string.h>
#include <openvml_reference.h>
static char* funcname[4]={"vsAdd", "vdAdd", "vcAdd","vzAdd"};
static double flop_per_elem[4]={1.0, 1.0, 2.0, 2.0};
static ab_y_func_t ref_vadd[] = {
(ab_y_func_t)OpenVML_FUNCNAME_REF(vsAdd),
(ab_y_func_t)OpenVML_FUNCNAME_REF(vdAdd),
(ab_y_func_t)OpenVML_FUNCNAME_REF(vcAdd),
(ab_y_func_t)OpenVML_FUNCNAME_REF(vzAdd),
};
static ab_y_func_t test_vadd[] = {
(ab_y_func_t)OpenVML_FUNCNAME(vsAdd),
(ab_y_func_t)OpenVML_FUNCNAME(vdAdd),
(ab_y_func_t)OpenVML_FUNCNAME(vcAdd),
(ab_y_func_t)OpenVML_FUNCNAME(vzAdd),
};
CTEST2(check_result_s, add){
run_test_ab_y(data->parameter, funcname, test_vadd, ref_vadd, flop_per_elem);
}
CTEST2(check_result_d, add){
run_test_ab_y(data->parameter, funcname, test_vadd, ref_vadd, flop_per_elem);
}
CTEST2(check_result_c, add){
run_test_ab_y(data->parameter, funcname, test_vadd, ref_vadd, flop_per_elem);
}
CTEST2(check_result_z, add){
run_test_ab_y(data->parameter, funcname, test_vadd, ref_vadd, flop_per_elem);
}

104
test/timer.c Normal file
View File

@ -0,0 +1,104 @@
/*
* Author: David Robert Nadeau
* Site: http://NadeauSoftware.com/
* License: Creative Commons Attribution 3.0 Unported License
* http://creativecommons.org/licenses/by/3.0/deed.en_US
*/
#if defined(_WIN32)
#include <Windows.h>
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>/* POSIX flags */
#include <time.h>/* clock_gettime(), time() */
#include <sys/time.h>/* gethrtime(), gettimeofday() */
#if defined(__MACH__) && defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif
#else
#error "Unable to define getRealTime( ) for an unknown OS."
#endif
/**
* Returns the real time, in seconds, or -1.0 if an error occurred.
*
* Time is measured since an arbitrary and OS-dependent start time.
* The returned real time is only useful for computing an elapsed time
* between two calls to this function.
*/
double getRealTime( )
{
#if defined(_WIN32)
FILETIME tm;
ULONGLONG t;
#if defined(NTDDI_WIN8) && NTDDI_VERSION >= NTDDI_WIN8
/* Windows 8, Windows Server 2012 and later. ---------------- */
GetSystemTimePreciseAsFileTime( &tm );
#else
/* Windows 2000 and later. ---------------------------------- */
GetSystemTimeAsFileTime( &tm );
#endif
t = ((ULONGLONG)tm.dwHighDateTime << 32) | (ULONGLONG)tm.dwLowDateTime;
return (double)t / 10000000.0;
#elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
/* HP-UX, Solaris. ------------------------------------------ */
return (double)gethrtime( ) / 1000000000.0;
#elif defined(__MACH__) && defined(__APPLE__)
/* OSX. ----------------------------------------------------- */
static double timeConvert = 0.0;
if ( timeConvert == 0.0 )
{
mach_timebase_info_data_t timeBase;
(void)mach_timebase_info( &timeBase );
timeConvert = (double)timeBase.numer /
(double)timeBase.denom /
1000000000.0;
}
return (double)mach_absolute_time( ) * timeConvert;
#elif defined(_POSIX_VERSION)
/* POSIX. --------------------------------------------------- */
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
{
struct timespec ts;
#if defined(CLOCK_MONOTONIC_PRECISE)
/* BSD. --------------------------------------------- */
const clockid_t id = CLOCK_MONOTONIC_PRECISE;
#elif defined(CLOCK_MONOTONIC_RAW)
/* Linux. ------------------------------------------- */
const clockid_t id = CLOCK_MONOTONIC_RAW;
#elif defined(CLOCK_HIGHRES)
/* Solaris. ----------------------------------------- */
const clockid_t id = CLOCK_HIGHRES;
#elif defined(CLOCK_MONOTONIC)
/* AIX, BSD, Linux, POSIX, Solaris. ----------------- */
const clockid_t id = CLOCK_MONOTONIC;
#elif defined(CLOCK_REALTIME)
/* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */
const clockid_t id = CLOCK_REALTIME;
#else
const clockid_t id = (clockid_t)-1;/* Unknown. */
#endif /* CLOCK_* */
if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )
return (double)ts.tv_sec +
(double)ts.tv_nsec / 1000000000.0;
/* Fall thru. */
}
#endif /* _POSIX_TIMERS */
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */
struct timeval tm;
gettimeofday( &tm, NULL );
return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0;
#else
return -1.0;/* Failed. */
#endif
}

48
test/vml_test.c Normal file
View File

@ -0,0 +1,48 @@
#include <stdio.h>
#define CTEST_MAIN
#include "vml_test.h"
CTEST_SETUP(check_result_s) {
init_test_parameter(&(data->parameter), 0, 0);
}
CTEST_SETUP(check_result_d) {
init_test_parameter(&(data->parameter), 0, 1);
}
CTEST_SETUP(check_result_c) {
init_test_parameter(&(data->parameter), 1, 0);
}
CTEST_SETUP(check_result_z) {
init_test_parameter(&(data->parameter), 1, 1);
}
CTEST_TEARDOWN(check_result_s) {
free_test_parameter(&(data->parameter));
}
CTEST_TEARDOWN(check_result_d) {
free_test_parameter(&(data->parameter));
}
CTEST_TEARDOWN(check_result_c) {
free_test_parameter(&(data->parameter));
}
CTEST_TEARDOWN(check_result_z) {
free_test_parameter(&(data->parameter));
}
int main(int argc, char ** argv){
int tmp_argc=1;
char ** tmp_argv=NULL;
init_input_arg(argc, argv);
ctest_main(argc, argv);
return 0;
}

76
test/vml_test.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef _VML_TEST_H_
#define _VML_TEST_H_
#include <stdlib.h>
#include <openvml.h>
#include "ctest.h"
#define STR_PASS "PASS"
#define STR_WARN "WARN"
#define STR_ERR "ERROR"
typedef struct {
double fail;
double warn;
} eps_t;
typedef struct {
void * a;
void * b;
void * y;
void * ref_a;
void * ref_b;
void * ref_y;
eps_t * eps;
VML_INT start;
VML_INT end;
VML_INT step;
int fp_type; //0 for real float, 1 for real double,
//2 for complex float, 3 for complex double
int element_size; //4 for float, 8 for double
int compose_size; //1 for real, 2 for complex
void * flushcache;
} perf_arg_t;
typedef struct{
VML_INT start;
VML_INT end;
VML_INT step;
} input_arg_t;
CTEST_DATA(check_result_s) {
perf_arg_t * parameter;
};
CTEST_DATA(check_result_d) {
perf_arg_t * parameter;
};
CTEST_DATA(check_result_c) {
perf_arg_t * parameter;
};
CTEST_DATA(check_result_z) {
perf_arg_t * parameter;
};
void * vml_test_memory_alloc(size_t size);
void vml_test_memory_free(void * ptr);
input_arg_t * get_input_arg();
void init_test_parameter(perf_arg_t ** p, int iscomplex, int isdouble);
void free_test_parameter(perf_arg_t ** p);
int check_result(double ref, double test, eps_t* thres);
void init_rand(VML_INT n, void * a, int iscomplex, int isdouble);
typedef void (*ab_y_func_t)(VML_INT, const void *, const void *, void *);
void run_test_ab_y(perf_arg_t * para, char* funcname[], ab_y_func_t*test_func, ab_y_func_t* ref_func,
double * flop_per_elem);
#endif

295
test/vml_util.c Normal file
View File

@ -0,0 +1,295 @@
#include "vml_test.h"
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#define FP_TYPE_NUM 4
//32MB
#define FLUSHCACHE_SIZE 32*1024*1024
static eps_t threshold[FP_TYPE_NUM]={{ 1e-04, 1e-05 },
{ 1e-13, 1e-14 }, // for d
{ 1e-04, 1e-05 }, // for c
{ 1e-13, 1e-14 }};
double getRealTime();
#define VML_TEST_LOG printf
void * vml_test_memory_alloc(size_t size)
{
void * ptr=NULL;
ptr=malloc(size);
if(ptr==NULL){
CTEST_ERR("memory alloc failed!\n");
exit(0);
}
return ptr;
}
void vml_test_memory_free(void * ptr)
{
free(ptr);
}
void print_help()
{
printf("-d <start> <end> <step>\n");
printf(" input data size.\n");
printf("-s test_suit\n");
printf(" testsuit name\n");
}
static input_arg_t input_args;
input_arg_t * get_input_arg()
{
return &input_args;
}
void init_input_arg(int argc, char *argv[])
{
input_args.start=100;
input_args.end=200;
input_args.step=10;
}
void init_test_parameter(perf_arg_t ** p, int iscomplex, int isdouble)
{
perf_arg_t * parameter=NULL;
int float_type_id=0;
parameter=(perf_arg_t*)vml_test_memory_alloc(sizeof(perf_arg_t));
memset(parameter,0,sizeof(perf_arg_t));
*p = parameter;
float_type_id=(iscomplex<<1)|(isdouble);
if(float_type_id<0 || float_type_id>=FP_TYPE_NUM) {
CTEST_ERR("Init data error!\n");
}
parameter->eps=&threshold[float_type_id];
parameter->fp_type=float_type_id;
parameter->element_size=(isdouble==0)?sizeof(float):sizeof(double);
parameter->compose_size=(iscomplex==0)?1:2;
parameter->start=input_args.start;
parameter->end=input_args.end;
parameter->step=input_args.step;
parameter->a=vml_test_memory_alloc(parameter->compose_size * parameter->element_size *
parameter->end);
parameter->y=vml_test_memory_alloc(parameter->compose_size * parameter->element_size *
parameter->end);
parameter->b=vml_test_memory_alloc(parameter->compose_size * parameter->element_size *
parameter->end);
parameter->ref_a=vml_test_memory_alloc(parameter->compose_size * parameter->element_size *
parameter->end);
parameter->ref_y=vml_test_memory_alloc(parameter->compose_size * parameter->element_size *
parameter->end);
parameter->ref_b=vml_test_memory_alloc(parameter->compose_size * parameter->element_size *
parameter->end);
parameter->flushcache=vml_test_memory_alloc(FLUSHCACHE_SIZE);
}
void free_test_parameter(perf_arg_t ** p)
{
perf_arg_t * parameter=*p;
if(*p == NULL) return;
if(parameter->a != NULL){
vml_test_memory_free(parameter->a);
parameter->a=NULL;
}
if(parameter->y != NULL){
vml_test_memory_free(parameter->y);
parameter->y=NULL;
}
if(parameter->y != NULL){
vml_test_memory_free(parameter->y);
parameter->y=NULL;
}
if(parameter->ref_a != NULL){
vml_test_memory_free(parameter->ref_a);
parameter->ref_a=NULL;
}
if(parameter->ref_y != NULL){
vml_test_memory_free(parameter->ref_y);
parameter->ref_y=NULL;
}
if(parameter->ref_b != NULL){
vml_test_memory_free(parameter->ref_b);
parameter->ref_b=NULL;
}
if(parameter->flushcache != NULL){
vml_test_memory_free(parameter->flushcache);
parameter->flushcache=NULL;
}
vml_test_memory_free(parameter);
}
int check_result(double ref, double test, eps_t* thres)
{
double tmp;
tmp=abs(ref-test);
if(tmp>=thres->warn && tmp<thres->fail) {
return 1; //warning
}else if (tmp >= thres->fail) {
return 2; //error
}else{
return 0; //pass
}
}
int check_vector(VML_INT n, void * ref, void * test, eps_t * thres, int iscomplex, int isdouble)
{
VML_INT i;
VML_INT length;
int result=0, max_result=0;
length=(iscomplex==0)? n : 2*n;
if(isdouble==0){
//float
float * ref_f=(float*)ref;
float * test_f=(float*)test;
for(i=0; i<length; i++){
result=check_result(ref_f[i], test_f[i], thres);
if(result>max_result) max_result=result;
}
}else{
//double
double* ref_d=(double*)ref;
double * test_d=(double*)test;
for(i=0; i<length; i++){
result=check_result(ref_d[i], test_d[i], thres);
if(result>max_result) max_result=result;
}
}
return max_result;
}
void init_rand_float(VML_INT n, float * a)
{
VML_INT i=0;
float e=5.0;
for(i=0; i<n; i++){
a[i]=((float)rand()/(float)(RAND_MAX)) * e;
}
}
void init_rand_double(VML_INT n, double * a)
{
VML_INT i=0;
double e=5.0;
for(i=0; i<n; i++){
a[i]=((double)rand()/(double)(RAND_MAX)) * e;
}
}
void init_rand(VML_INT n, void * a, int iscomplex, int isdouble)
{
VML_INT length;
length=(iscomplex==0)? n: 2*n;
if(isdouble==0){
init_rand_float(length, (float*)a);
}else{
init_rand_double(length, (double*)a);
}
}
void flush_cache(void * flushcache)
{
if(flushcache!=NULL){
memset(flushcache, 1, FLUSHCACHE_SIZE);
}
}
void run_test_ab_y(perf_arg_t * para, char* funcname[], ab_y_func_t test_func[], ab_y_func_t ref_func[],
double * flops_per_elem)
{
VML_INT start=para->start;
VML_INT end=para->end;
VML_INT step=para->step;
double mflops=0.0;
double time=0.0, start_time, end_time;
int iscomplex = (para->fp_type & 0x2) >> 1;
int isdouble = (para->fp_type & 0x1);
int result=0;
char * result_str;
int failed_count=0;
VML_INT i;
VML_TEST_LOG("\n");
VML_TEST_LOG("Func\tN\tMFlops\t\tTime(s)\t\tResult\n");
init_rand(end, para->a, iscomplex, isdouble);
init_rand(end, para->b, iscomplex, isdouble);
memcpy(para->ref_a, para->a, end * para->element_size * para->compose_size);
memcpy(para->ref_b, para->b, end * para->element_size * para->compose_size);
for(i=start; i<=end; i+=step) {
mflops=flops_per_elem[para->fp_type] * i;
//need to clean cache
//flush_cache(para->flushcache);
start_time=getRealTime();
test_func[para->fp_type](i, para->a, para->b, para->y);
end_time=getRealTime();
time=end_time-start_time;
mflops=mflops/(double)(1000000)/time;
ref_func[para->fp_type](i, para->ref_a, para->ref_b, para->ref_y);
//check
result=check_vector(i, para->ref_y, para->y, para->eps, iscomplex, isdouble);
if(result==0){
result_str=STR_PASS;
}else if(result==1){
result_str=STR_WARN;
}else{
result_str=STR_ERR;
failed_count++;
}
VML_TEST_LOG("%s\t%d\t%lf\t%lf\t%s\n", funcname[para->fp_type], i, mflops, time, result_str);
}
if(failed_count>0) CTEST_ERR("Result failed!\n");
}