summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Foster2011-01-12 19:20:35 -0800
committerNick Foster2011-01-12 19:20:35 -0800
commitc77bb3e71562daa68e9a195a0131b7cc04324784 (patch)
tree7d6c851463de22ca53174f8499ec74b53eecac52
parentc501dc110d3cc7cfcfff178fecb21f30ac9bd54c (diff)
downloadgnuradio-c77bb3e71562daa68e9a195a0131b7cc04324784.tar.gz
gnuradio-c77bb3e71562daa68e9a195a0131b7cc04324784.tar.bz2
gnuradio-c77bb3e71562daa68e9a195a0131b7cc04324784.zip
Volk: Working on a new QA architecture that doesn't require individual test programs.
-rw-r--r--volk/lib/Makefile.am2
-rw-r--r--volk/lib/qa_32fc_32f_multiply_aligned16.cc6
-rw-r--r--volk/lib/qa_8sc_deinterleave_16s_aligned16.cc2
-rw-r--r--volk/lib/qa_utils.cc223
-rw-r--r--volk/lib/qa_utils.h19
-rw-r--r--volk/lib/qa_volk.cc2
6 files changed, 247 insertions, 7 deletions
diff --git a/volk/lib/Makefile.am b/volk/lib/Makefile.am
index 0aeafe4aa..a10b0a362 100644
--- a/volk/lib/Makefile.am
+++ b/volk/lib/Makefile.am
@@ -156,7 +156,6 @@ endif
# ----------------------------------------------------------------
libvolk_qa_la_SOURCES = \
qa_volk.cc \
- qa_utils.cc \
qa_16s_quad_max_star_aligned16.cc \
qa_32fc_dot_prod_aligned16.cc \
qa_32fc_square_dist_aligned16.cc \
@@ -181,7 +180,6 @@ libvolk_qa_la_SOURCES = \
qa_32f_dot_prod_aligned16.cc \
qa_32f_dot_prod_unaligned16.cc \
qa_32f_fm_detect_aligned16.cc \
- qa_32fc_32f_multiply_aligned16.cc \
qa_32fc_multiply_aligned16.cc \
qa_32f_divide_aligned16.cc \
qa_32f_multiply_aligned16.cc \
diff --git a/volk/lib/qa_32fc_32f_multiply_aligned16.cc b/volk/lib/qa_32fc_32f_multiply_aligned16.cc
index 7bb8d21c1..b80e0e008 100644
--- a/volk/lib/qa_32fc_32f_multiply_aligned16.cc
+++ b/volk/lib/qa_32fc_32f_multiply_aligned16.cc
@@ -5,10 +5,11 @@
#include <time.h>
#include <string.h>
#include <qa_utils.h>
+#include <boost/test/unit_test.hpp>
-#define ERR_DELTA (1e-4)
+#define TOLERANCE (1e-4)
-void qa_32fc_32f_multiply_aligned16::t1() {
+void qa_32fc_32f_multiply_aligned16(void) {
const int vlen = 2046;
const int ITERS = 100000;
@@ -72,4 +73,3 @@ void qa_32fc_32f_multiply_aligned16::t1() {
free(results[i]);
}
}
-
diff --git a/volk/lib/qa_8sc_deinterleave_16s_aligned16.cc b/volk/lib/qa_8sc_deinterleave_16s_aligned16.cc
index 94e63e37d..f753e1107 100644
--- a/volk/lib/qa_8sc_deinterleave_16s_aligned16.cc
+++ b/volk/lib/qa_8sc_deinterleave_16s_aligned16.cc
@@ -40,7 +40,7 @@ void qa_8sc_deinterleave_16s_aligned16::t1() {
start = clock();
for(int count = 0; count < ITERS; ++count) {
- volk_8sc_deinterleave_16s_aligned16_manual(output_generic, output_generic1, input0, vlen, "generic");
+ volk_8sc_deinterleave_16s_aligned16_manual(output_generic, output_generic1, input0, vlen, "monkeys");
}
end = clock();
total = (double)(end-start)/(double)CLOCKS_PER_SEC;
diff --git a/volk/lib/qa_utils.cc b/volk/lib/qa_utils.cc
new file mode 100644
index 000000000..4d93ca62a
--- /dev/null
+++ b/volk/lib/qa_utils.cc
@@ -0,0 +1,223 @@
+#include "qa_utils.h"
+#include <stdlib.h>
+#include <boost/foreach.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/test/unit_test.hpp>
+#include <iostream>
+#include <vector>
+#include <time.h>
+//#include <math.h>
+//#include <volk/volk_runtime.h>
+#include <volk/volk_registry.h>
+#include <volk/volk.h>
+#include <boost/typeof/typeof.hpp>
+#include <boost/type_traits.hpp>
+//#include <boost/test/unit_test.hpp>
+
+float uniform() {
+ return 2.0 * ((float) rand() / RAND_MAX - 0.5); // uniformly (-1, 1)
+}
+
+void
+random_floats (float *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++)
+ buf[i] = uniform ();
+}
+
+template <class t>
+t *make_aligned_buffer(unsigned int len) {
+ t *buf;
+ int ret;
+ ret = posix_memalign((void**)&buf, 16, len * sizeof(t));
+ assert(ret == 0);
+ return buf;
+}
+
+void make_buffer_for_signature(std::vector<void *> &buffs, std::vector<std::string> inputsig, unsigned int vlen) {
+ BOOST_FOREACH(std::string sig, inputsig) {
+ if (sig=="32fc" || sig=="64f") buffs.push_back((void *) make_aligned_buffer<lv_32fc_t>(vlen));
+ else if(sig=="32f" || sig=="32u" || sig=="32s" || sig=="16sc") buffs.push_back((void *) make_aligned_buffer<float>(vlen));
+ else if(sig=="16s" || sig=="16u") buffs.push_back((void *) make_aligned_buffer<int16_t>(vlen));
+ else if(sig=="8s" || sig=="8u") buffs.push_back((void *) make_aligned_buffer<int8_t>(vlen));
+ else std::cout << "Invalid type!" << std::endl;
+ }
+}
+
+static std::vector<std::string> get_arch_list(const int archs[]) {
+ std::vector<std::string> archlist;
+ int num_archs = archs[0];
+
+ //there has got to be a way to query these arches
+ for(int i = 0; i < num_archs; i++) {
+ switch(archs[i+1]) {
+ case (1<<LV_GENERIC):
+ archlist.push_back("generic");
+ break;
+ case (1<<LV_ORC):
+ archlist.push_back("orc");
+ break;
+ case (1<<LV_SSE):
+ archlist.push_back("sse");
+ break;
+ case (1<<LV_SSE2):
+ archlist.push_back("sse2");
+ break;
+ case (1<<LV_SSSE3):
+ archlist.push_back("ssse3");
+ break;
+ case (1<<LV_SSE4_1):
+ archlist.push_back("sse4_1");
+ break;
+ case (1<<LV_SSE4_2):
+ archlist.push_back("sse4_2");
+ break;
+ case (1<<LV_SSE4_A):
+ archlist.push_back("sse4_a");
+ break;
+ case (1<<LV_MMX):
+ archlist.push_back("mmx");
+ break;
+ case (1<<LV_AVX):
+ archlist.push_back("avx");
+ break;
+ default:
+ break;
+ }
+ }
+ return archlist;
+}
+
+static bool is_valid_type(std::string type) {
+ std::vector<std::string> valid_types = boost::assign::list_of("32fc")("32f")("32s")("32u")("16sc")("16s")("16u")("8s")("8u");
+
+ BOOST_FOREACH(std::string this_type, valid_types) {
+ if(type == this_type) return true;
+ }
+ return false;
+}
+
+
+static void get_function_signature(std::vector<std::string> &inputsig,
+ std::vector<std::string> &outputsig,
+ std::string name) {
+ boost::char_separator<char> sep("_");
+ boost::tokenizer<boost::char_separator<char> > tok(name, sep);
+ std::vector<std::string> toked;
+ tok.assign(name);
+ toked.assign(tok.begin(), tok.end());
+
+ assert(toked[0] == "volk");
+
+ inputsig.push_back(toked[1]); //mandatory
+ int pos = 2;
+ bool valid_type = true;
+ while(valid_type && pos < toked.size()) {
+ if(is_valid_type(toked[pos])) inputsig.push_back(toked[pos]);
+ else valid_type = false;
+ pos++;
+ }
+ while(!valid_type && pos < toked.size()) {
+ if(is_valid_type(toked[pos])) valid_type = true;
+ pos++;
+ }
+ while(valid_type && pos < toked.size()) {
+ if(is_valid_type(toked[pos])) outputsig.push_back(toked[pos]);
+ else valid_type = false;
+ pos++;
+ }
+
+ //if there's no explicit output sig then assume the output is the same as the first input
+ if(outputsig.size() == 0) outputsig.push_back(inputsig[0]);
+ assert(inputsig.size() != 0);
+ assert(outputsig.size() != 0);
+}
+
+inline void run_cast_test2(volk_fn_2arg func, void *outbuff, std::vector<void *> &inbuffs, unsigned int vlen, unsigned int iter, std::string arch) {
+ while(iter--) func(outbuff, inbuffs[0], vlen, arch.c_str());
+}
+
+inline void run_cast_test3(volk_fn_3arg func, void *outbuff, std::vector<void *> &inbuffs, unsigned int vlen, unsigned int iter, std::string arch) {
+ while(iter--) func(outbuff, inbuffs[0], inbuffs[1], vlen, arch.c_str());
+}
+
+inline void run_cast_test4(volk_fn_4arg func, void *outbuff, std::vector<void *> &inbuffs, unsigned int vlen, unsigned int iter, std::string arch) {
+ while(iter--) func(outbuff, inbuffs[0], inbuffs[1], inbuffs[2], vlen, arch.c_str());
+}
+
+bool run_volk_tests(const int archs[], void (*manual_func)(), std::string name, float tol, int vlen, int iter) {
+ std::cout << "RUN_VOLK_TESTS: " << name << std::endl;
+
+ //first let's get a list of available architectures for the test
+ std::vector<std::string> arch_list = get_arch_list(archs);
+
+ BOOST_FOREACH(std::string arch, arch_list) {
+ std::cout << "Found an arch: " << arch << std::endl;
+ }
+
+ //now we have to get a function signature by parsing the name
+ std::vector<std::string> inputsig, outputsig;
+ get_function_signature(inputsig, outputsig, name);
+
+ for(int i=0; i<inputsig.size(); i++) std::cout << "Input: " << inputsig[i] << std::endl;
+ for(int i=0; i<outputsig.size(); i++) std::cout << "Output: " << outputsig[i] << std::endl;
+
+ //now that we have that, we'll set up input and output buffers based on the function signature
+ std::vector<void *> inbuffs;
+ make_buffer_for_signature(inbuffs, inputsig, vlen);
+
+ //and set the input buffers to something random
+ //TODO
+
+ //allocate output buffers -- one for each output for each arch
+ std::vector<void *> outbuffs;
+ BOOST_FOREACH(std::string arch, arch_list) {
+ make_buffer_for_signature(outbuffs, outputsig, vlen);
+ }
+
+ //now run the test
+ clock_t start, end;
+ for(int i = 0; i < arch_list.size(); i++) {
+ start = clock();
+ switch(outputsig.size()+inputsig.size()) {
+ case 2:
+ run_cast_test2((volk_fn_2arg)(manual_func), outbuffs[i], inbuffs, vlen, iter, arch_list[i]);
+ break;
+ case 3:
+ run_cast_test3((volk_fn_3arg)(manual_func), outbuffs[i], inbuffs, vlen, iter, arch_list[i]);
+ break;
+ case 4:
+ run_cast_test4((volk_fn_4arg)(manual_func), outbuffs[i], inbuffs, vlen, iter, arch_list[i]);
+ break;
+ default:
+ break;
+ }
+ end = clock();
+ std::cout << arch_list[i] << " completed in " << (double)(end-start)/(double)CLOCKS_PER_SEC << "s" << std::endl;
+ }
+
+ //and now compare each output to the generic output
+ //first we have to know which output is the generic one, they aren't in order...
+ int generic_offset;
+ for(int i=0; i<arch_list.size(); i++)
+ if(arch_list[i] == "generic") generic_offset=i;
+
+ for(int i=0; i<arch_list.size(); i++) {
+ if(arch_list[i] != "generic") {
+ for(int j=0; i<vlen; j++) {
+ BOOST_CHECK_CLOSE(((float *)(outbuffs[generic_offset]))[j], ((float *)(outbuffs[i]))[j], tol);
+ }
+ }
+ }
+
+ BOOST_FOREACH(void *buf, inbuffs) {
+ free(buf);
+ }
+ BOOST_FOREACH(void *buf, outbuffs) {
+ free(buf);
+ }
+ return 0;
+}
+
+
diff --git a/volk/lib/qa_utils.h b/volk/lib/qa_utils.h
new file mode 100644
index 000000000..80323c445
--- /dev/null
+++ b/volk/lib/qa_utils.h
@@ -0,0 +1,19 @@
+#ifndef VOLK_QA_UTILS_H
+#define VOLK_QA_UTILS_H
+
+#include <stdlib.h>
+#include <string>
+#include <volk/volk.h>
+
+float uniform(void);
+void random_floats(float *buf, unsigned n);
+
+bool run_volk_tests(const int[], void(*)(), std::string, float, int, int);
+
+#define VOLK_RUN_TESTS(func, tol, len, iter) run_volk_tests(func##_arch_defs, (void (*)())func##_manual, std::string(#func), tol, len, iter)
+
+typedef void (*volk_fn_2arg)(void *, void *, unsigned int, const char*);
+typedef void (*volk_fn_3arg)(void *, void *, void *, unsigned int, const char*);
+typedef void (*volk_fn_4arg)(void *, void *, void *, void *, unsigned int, const char*);
+
+#endif //VOLK_QA_UTILS_H
diff --git a/volk/lib/qa_volk.cc b/volk/lib/qa_volk.cc
index c3c27b69b..8e7e59768 100644
--- a/volk/lib/qa_volk.cc
+++ b/volk/lib/qa_volk.cc
@@ -143,7 +143,7 @@ qa_volk::suite()
s->addTest(qa_32f_dot_prod_aligned16::suite());
s->addTest(qa_32f_dot_prod_unaligned16::suite());
s->addTest(qa_32f_fm_detect_aligned16::suite());
- s->addTest(qa_32fc_32f_multiply_aligned16::suite());
+ //s->addTest(qa_32fc_32f_multiply_aligned16::suite());
s->addTest(qa_32fc_multiply_aligned16::suite());
s->addTest(qa_32f_divide_aligned16::suite());
s->addTest(qa_32f_multiply_aligned16::suite());