Initial snapshot: hand motion pipeline (Dyn-HaMR + dex-retargeting + SPIDER)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 14:13:49 +08:00
commit 7e4ef6f98b
7002 changed files with 1452249 additions and 0 deletions
@@ -0,0 +1,149 @@
#include <Eigen/Sparse>
#include <bench/BenchTimer.h>
#include <set>
using namespace std;
using namespace Eigen;
using namespace Eigen;
#ifndef SIZE
#define SIZE 1024
#endif
#ifndef DENSITY
#define DENSITY 0.01
#endif
#ifndef SCALAR
#define SCALAR double
#endif
typedef SCALAR Scalar;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
typedef SparseMatrix<Scalar> EigenSparseMatrix;
void fillMatrix(float density, int rows, int cols, EigenSparseMatrix& dst)
{
dst.reserve(double(rows)*cols*density);
for(int j = 0; j < cols; j++)
{
for(int i = 0; i < rows; i++)
{
Scalar v = (internal::random<float>(0,1) < density) ? internal::random<Scalar>() : 0;
if (v!=0)
dst.insert(i,j) = v;
}
}
dst.finalize();
}
void fillMatrix2(int nnzPerCol, int rows, int cols, EigenSparseMatrix& dst)
{
// std::cout << "alloc " << nnzPerCol*cols << "\n";
dst.reserve(nnzPerCol*cols);
for(int j = 0; j < cols; j++)
{
std::set<int> aux;
for(int i = 0; i < nnzPerCol; i++)
{
int k = internal::random<int>(0,rows-1);
while (aux.find(k)!=aux.end())
k = internal::random<int>(0,rows-1);
aux.insert(k);
dst.insert(k,j) = internal::random<Scalar>();
}
}
dst.finalize();
}
void eiToDense(const EigenSparseMatrix& src, DenseMatrix& dst)
{
dst.setZero();
for (int j=0; j<src.cols(); ++j)
for (EigenSparseMatrix::InnerIterator it(src.derived(), j); it; ++it)
dst(it.index(),j) = it.value();
}
#ifndef NOGMM
#include "gmm/gmm.h"
typedef gmm::csc_matrix<Scalar> GmmSparse;
typedef gmm::col_matrix< gmm::wsvector<Scalar> > GmmDynSparse;
void eiToGmm(const EigenSparseMatrix& src, GmmSparse& dst)
{
GmmDynSparse tmp(src.rows(), src.cols());
for (int j=0; j<src.cols(); ++j)
for (EigenSparseMatrix::InnerIterator it(src.derived(), j); it; ++it)
tmp(it.index(),j) = it.value();
gmm::copy(tmp, dst);
}
#endif
#ifndef NOMTL
#include <boost/numeric/mtl/mtl.hpp>
typedef mtl::compressed2D<Scalar, mtl::matrix::parameters<mtl::tag::col_major> > MtlSparse;
typedef mtl::compressed2D<Scalar, mtl::matrix::parameters<mtl::tag::row_major> > MtlSparseRowMajor;
void eiToMtl(const EigenSparseMatrix& src, MtlSparse& dst)
{
mtl::matrix::inserter<MtlSparse> ins(dst);
for (int j=0; j<src.cols(); ++j)
for (EigenSparseMatrix::InnerIterator it(src.derived(), j); it; ++it)
ins[it.index()][j] = it.value();
}
#endif
#ifdef CSPARSE
extern "C" {
#include "cs.h"
}
void eiToCSparse(const EigenSparseMatrix& src, cs* &dst)
{
cs* aux = cs_spalloc (0, 0, 1, 1, 1);
for (int j=0; j<src.cols(); ++j)
for (EigenSparseMatrix::InnerIterator it(src.derived(), j); it; ++it)
if (!cs_entry(aux, it.index(), j, it.value()))
{
std::cout << "cs_entry error\n";
exit(2);
}
dst = cs_compress(aux);
// cs_spfree(aux);
}
#endif // CSPARSE
#ifndef NOUBLAS
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/vector_sparse.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/vector_of_vector.hpp>
#include <boost/numeric/ublas/operation.hpp>
typedef boost::numeric::ublas::compressed_matrix<Scalar,boost::numeric::ublas::column_major> UBlasSparse;
void eiToUblas(const EigenSparseMatrix& src, UBlasSparse& dst)
{
dst.resize(src.rows(), src.cols(), false);
for (int j=0; j<src.cols(); ++j)
for (EigenSparseMatrix::InnerIterator it(src.derived(), j); it; ++it)
dst(it.index(),j) = it.value();
}
template <typename EigenType, typename UblasType>
void eiToUblasVec(const EigenType& src, UblasType& dst)
{
dst.resize(src.size());
for (int j=0; j<src.size(); ++j)
dst[j] = src.coeff(j);
}
#endif
#ifdef OSKI
extern "C" {
#include <oski/oski.h>
}
#endif
@@ -0,0 +1,199 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_BENCH_TIMERR_H
#define EIGEN_BENCH_TIMERR_H
#if defined(_WIN32) || defined(__CYGWIN__)
# ifndef NOMINMAX
# define NOMINMAX
# define EIGEN_BT_UNDEF_NOMINMAX
# endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# define EIGEN_BT_UNDEF_WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
#elif defined(__APPLE__)
#include <mach/mach_time.h>
#else
# include <unistd.h>
#endif
static void escape(void *p) {
#if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
asm volatile("" : : "g"(p) : "memory");
#endif
}
static void clobber() {
#if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
asm volatile("" : : : "memory");
#endif
}
#include <Eigen/Core>
namespace Eigen
{
enum {
CPU_TIMER = 0,
REAL_TIMER = 1
};
/** Elapsed time timer keeping the best try.
*
* On POSIX platforms we use clock_gettime with CLOCK_PROCESS_CPUTIME_ID.
* On Windows we use QueryPerformanceCounter
*
* Important: on linux, you must link with -lrt
*/
class BenchTimer
{
public:
BenchTimer()
{
#if defined(_WIN32) || defined(__CYGWIN__)
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
m_frequency = (double)freq.QuadPart;
#endif
reset();
}
~BenchTimer() {}
inline void reset()
{
m_bests.fill(1e9);
m_worsts.fill(0);
m_totals.setZero();
}
inline void start()
{
m_starts[CPU_TIMER] = getCpuTime();
m_starts[REAL_TIMER] = getRealTime();
}
inline void stop()
{
m_times[CPU_TIMER] = getCpuTime() - m_starts[CPU_TIMER];
m_times[REAL_TIMER] = getRealTime() - m_starts[REAL_TIMER];
#if EIGEN_VERSION_AT_LEAST(2,90,0)
m_bests = m_bests.cwiseMin(m_times);
m_worsts = m_worsts.cwiseMax(m_times);
#else
m_bests(0) = std::min(m_bests(0),m_times(0));
m_bests(1) = std::min(m_bests(1),m_times(1));
m_worsts(0) = std::max(m_worsts(0),m_times(0));
m_worsts(1) = std::max(m_worsts(1),m_times(1));
#endif
m_totals += m_times;
}
/** Return the elapsed time in seconds between the last start/stop pair
*/
inline double value(int TIMER = CPU_TIMER) const
{
return m_times[TIMER];
}
/** Return the best elapsed time in seconds
*/
inline double best(int TIMER = CPU_TIMER) const
{
return m_bests[TIMER];
}
/** Return the worst elapsed time in seconds
*/
inline double worst(int TIMER = CPU_TIMER) const
{
return m_worsts[TIMER];
}
/** Return the total elapsed time in seconds.
*/
inline double total(int TIMER = CPU_TIMER) const
{
return m_totals[TIMER];
}
inline double getCpuTime() const
{
#ifdef _WIN32
LARGE_INTEGER query_ticks;
QueryPerformanceCounter(&query_ticks);
return query_ticks.QuadPart/m_frequency;
#elif __APPLE__
return double(mach_absolute_time())*1e-9;
#else
timespec ts;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
return double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec);
#endif
}
inline double getRealTime() const
{
#ifdef _WIN32
SYSTEMTIME st;
GetSystemTime(&st);
return (double)st.wSecond + 1.e-3 * (double)st.wMilliseconds;
#elif __APPLE__
return double(mach_absolute_time())*1e-9;
#else
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return double(ts.tv_sec) + 1e-9 * double(ts.tv_nsec);
#endif
}
protected:
#if defined(_WIN32) || defined(__CYGWIN__)
double m_frequency;
#endif
Vector2d m_starts;
Vector2d m_times;
Vector2d m_bests;
Vector2d m_worsts;
Vector2d m_totals;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
#define BENCH(TIMER,TRIES,REP,CODE) { \
TIMER.reset(); \
for(int uglyvarname1=0; uglyvarname1<TRIES; ++uglyvarname1){ \
TIMER.start(); \
for(int uglyvarname2=0; uglyvarname2<REP; ++uglyvarname2){ \
CODE; \
} \
TIMER.stop(); \
clobber(); \
} \
}
}
// clean #defined tokens
#ifdef EIGEN_BT_UNDEF_NOMINMAX
# undef EIGEN_BT_UNDEF_NOMINMAX
# undef NOMINMAX
#endif
#ifdef EIGEN_BT_UNDEF_WIN32_LEAN_AND_MEAN
# undef EIGEN_BT_UNDEF_WIN32_LEAN_AND_MEAN
# undef WIN32_LEAN_AND_MEAN
#endif
#endif // EIGEN_BENCH_TIMERR_H
@@ -0,0 +1,92 @@
#ifndef EIGEN_BENCH_UTIL_H
#define EIGEN_BENCH_UTIL_H
#include <Eigen/Core>
#include "BenchTimer.h"
using namespace std;
using namespace Eigen;
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition.hpp>
#include <boost/preprocessor/seq.hpp>
#include <boost/preprocessor/array.hpp>
#include <boost/preprocessor/arithmetic.hpp>
#include <boost/preprocessor/comparison.hpp>
#include <boost/preprocessor/punctuation.hpp>
#include <boost/preprocessor/punctuation/comma.hpp>
#include <boost/preprocessor/stringize.hpp>
template<typename MatrixType> void initMatrix_random(MatrixType& mat) __attribute__((noinline));
template<typename MatrixType> void initMatrix_random(MatrixType& mat)
{
mat.setRandom();// = MatrixType::random(mat.rows(), mat.cols());
}
template<typename MatrixType> void initMatrix_identity(MatrixType& mat) __attribute__((noinline));
template<typename MatrixType> void initMatrix_identity(MatrixType& mat)
{
mat.setIdentity();
}
#ifndef __INTEL_COMPILER
#define DISABLE_SSE_EXCEPTIONS() { \
int aux; \
asm( \
"stmxcsr %[aux] \n\t" \
"orl $32832, %[aux] \n\t" \
"ldmxcsr %[aux] \n\t" \
: : [aux] "m" (aux)); \
}
#else
#define DISABLE_SSE_EXCEPTIONS()
#endif
#ifdef BENCH_GMM
#include <gmm/gmm.h>
template <typename EigenMatrixType, typename GmmMatrixType>
void eiToGmm(const EigenMatrixType& src, GmmMatrixType& dst)
{
dst.resize(src.rows(),src.cols());
for (int j=0; j<src.cols(); ++j)
for (int i=0; i<src.rows(); ++i)
dst(i,j) = src.coeff(i,j);
}
#endif
#ifdef BENCH_GSL
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_eigen.h>
template <typename EigenMatrixType>
void eiToGsl(const EigenMatrixType& src, gsl_matrix** dst)
{
for (int j=0; j<src.cols(); ++j)
for (int i=0; i<src.rows(); ++i)
gsl_matrix_set(*dst, i, j, src.coeff(i,j));
}
#endif
#ifdef BENCH_UBLAS
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>
template <typename EigenMatrixType, typename UblasMatrixType>
void eiToUblas(const EigenMatrixType& src, UblasMatrixType& dst)
{
dst.resize(src.rows(),src.cols());
for (int j=0; j<src.cols(); ++j)
for (int i=0; i<src.rows(); ++i)
dst(i,j) = src.coeff(i,j);
}
template <typename EigenType, typename UblasType>
void eiToUblasVec(const EigenType& src, UblasType& dst)
{
dst.resize(src.size());
for (int j=0; j<src.size(); ++j)
dst[j] = src.coeff(j);
}
#endif
#endif // EIGEN_BENCH_UTIL_H
@@ -0,0 +1,55 @@
This folder contains a couple of benchmark utities and Eigen benchmarks.
****************************
* bench_multi_compilers.sh *
****************************
This script allows to run a benchmark on a set of different compilers/compiler options.
It takes two arguments:
- a file defining the list of the compilers with their options
- the .cpp file of the benchmark
Examples:
$ ./bench_multi_compilers.sh basicbench.cxxlist basicbenchmark.cpp
g++-4.1 -O3 -DNDEBUG -finline-limit=10000
3d-3x3 / 4d-4x4 / Xd-4x4 / Xd-20x20 /
0.271102 0.131416 0.422322 0.198633
0.201658 0.102436 0.397566 0.207282
g++-4.2 -O3 -DNDEBUG -finline-limit=10000
3d-3x3 / 4d-4x4 / Xd-4x4 / Xd-20x20 /
0.107805 0.0890579 0.30265 0.161843
0.127157 0.0712581 0.278341 0.191029
g++-4.3 -O3 -DNDEBUG -finline-limit=10000
3d-3x3 / 4d-4x4 / Xd-4x4 / Xd-20x20 /
0.134318 0.105291 0.3704 0.180966
0.137703 0.0732472 0.31225 0.202204
icpc -fast -DNDEBUG -fno-exceptions -no-inline-max-size
3d-3x3 / 4d-4x4 / Xd-4x4 / Xd-20x20 /
0.226145 0.0941319 0.371873 0.159433
0.109302 0.0837538 0.328102 0.173891
$ ./bench_multi_compilers.sh ompbench.cxxlist ompbenchmark.cpp
g++-4.2 -O3 -DNDEBUG -finline-limit=10000 -fopenmp
double, fixed-size 4x4: 0.00165105s 0.0778739s
double, 32x32: 0.0654769s 0.075289s => x0.869674 (2)
double, 128x128: 0.054148s 0.0419669s => x1.29025 (2)
double, 512x512: 0.913799s 0.428533s => x2.13239 (2)
double, 1024x1024: 14.5972s 9.3542s => x1.5605 (2)
icpc -fast -DNDEBUG -fno-exceptions -no-inline-max-size -openmp
double, fixed-size 4x4: 0.000589848s 0.019949s
double, 32x32: 0.0682781s 0.0449722s => x1.51823 (2)
double, 128x128: 0.0547509s 0.0435519s => x1.25714 (2)
double, 512x512: 0.829436s 0.424438s => x1.9542 (2)
double, 1024x1024: 14.5243s 10.7735s => x1.34815 (2)
@@ -0,0 +1,876 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2015 Benoit Jacob <benoitjacob@google.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <iostream>
#include <cstdint>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <fstream>
#include <string>
#include <cmath>
#include <cassert>
#include <cstring>
#include <memory>
#include <Eigen/Core>
using namespace std;
const int default_precision = 4;
// see --only-cubic-sizes
bool only_cubic_sizes = false;
// see --dump-tables
bool dump_tables = false;
uint8_t log2_pot(size_t x) {
size_t l = 0;
while (x >>= 1) l++;
return l;
}
uint16_t compact_size_triple(size_t k, size_t m, size_t n)
{
return (log2_pot(k) << 8) | (log2_pot(m) << 4) | log2_pot(n);
}
// just a helper to store a triple of K,M,N sizes for matrix product
struct size_triple_t
{
uint16_t k, m, n;
size_triple_t() : k(0), m(0), n(0) {}
size_triple_t(size_t _k, size_t _m, size_t _n) : k(_k), m(_m), n(_n) {}
size_triple_t(const size_triple_t& o) : k(o.k), m(o.m), n(o.n) {}
size_triple_t(uint16_t compact)
{
k = 1 << ((compact & 0xf00) >> 8);
m = 1 << ((compact & 0x0f0) >> 4);
n = 1 << ((compact & 0x00f) >> 0);
}
bool is_cubic() const { return k == m && m == n; }
};
ostream& operator<<(ostream& s, const size_triple_t& t)
{
return s << "(" << t.k << ", " << t.m << ", " << t.n << ")";
}
struct inputfile_entry_t
{
uint16_t product_size;
uint16_t pot_block_size;
size_triple_t nonpot_block_size;
float gflops;
};
struct inputfile_t
{
enum class type_t {
unknown,
all_pot_sizes,
default_sizes
};
string filename;
vector<inputfile_entry_t> entries;
type_t type;
inputfile_t(const string& fname)
: filename(fname)
, type(type_t::unknown)
{
ifstream stream(filename);
if (!stream.is_open()) {
cerr << "couldn't open input file: " << filename << endl;
exit(1);
}
string line;
while (getline(stream, line)) {
if (line.empty()) continue;
if (line.find("BEGIN MEASUREMENTS ALL POT SIZES") == 0) {
if (type != type_t::unknown) {
cerr << "Input file " << filename << " contains redundant BEGIN MEASUREMENTS lines";
exit(1);
}
type = type_t::all_pot_sizes;
continue;
}
if (line.find("BEGIN MEASUREMENTS DEFAULT SIZES") == 0) {
if (type != type_t::unknown) {
cerr << "Input file " << filename << " contains redundant BEGIN MEASUREMENTS lines";
exit(1);
}
type = type_t::default_sizes;
continue;
}
if (type == type_t::unknown) {
continue;
}
switch(type) {
case type_t::all_pot_sizes: {
unsigned int product_size, block_size;
float gflops;
int sscanf_result =
sscanf(line.c_str(), "%x %x %f",
&product_size,
&block_size,
&gflops);
if (3 != sscanf_result ||
!product_size ||
product_size > 0xfff ||
!block_size ||
block_size > 0xfff ||
!isfinite(gflops))
{
cerr << "ill-formed input file: " << filename << endl;
cerr << "offending line:" << endl << line << endl;
exit(1);
}
if (only_cubic_sizes && !size_triple_t(product_size).is_cubic()) {
continue;
}
inputfile_entry_t entry;
entry.product_size = uint16_t(product_size);
entry.pot_block_size = uint16_t(block_size);
entry.gflops = gflops;
entries.push_back(entry);
break;
}
case type_t::default_sizes: {
unsigned int product_size;
float gflops;
int bk, bm, bn;
int sscanf_result =
sscanf(line.c_str(), "%x default(%d, %d, %d) %f",
&product_size,
&bk, &bm, &bn,
&gflops);
if (5 != sscanf_result ||
!product_size ||
product_size > 0xfff ||
!isfinite(gflops))
{
cerr << "ill-formed input file: " << filename << endl;
cerr << "offending line:" << endl << line << endl;
exit(1);
}
if (only_cubic_sizes && !size_triple_t(product_size).is_cubic()) {
continue;
}
inputfile_entry_t entry;
entry.product_size = uint16_t(product_size);
entry.pot_block_size = 0;
entry.nonpot_block_size = size_triple_t(bk, bm, bn);
entry.gflops = gflops;
entries.push_back(entry);
break;
}
default:
break;
}
}
stream.close();
if (type == type_t::unknown) {
cerr << "Unrecognized input file " << filename << endl;
exit(1);
}
if (entries.empty()) {
cerr << "didn't find any measurements in input file: " << filename << endl;
exit(1);
}
}
};
struct preprocessed_inputfile_entry_t
{
uint16_t product_size;
uint16_t block_size;
float efficiency;
};
bool lower_efficiency(const preprocessed_inputfile_entry_t& e1, const preprocessed_inputfile_entry_t& e2)
{
return e1.efficiency < e2.efficiency;
}
struct preprocessed_inputfile_t
{
string filename;
vector<preprocessed_inputfile_entry_t> entries;
preprocessed_inputfile_t(const inputfile_t& inputfile)
: filename(inputfile.filename)
{
if (inputfile.type != inputfile_t::type_t::all_pot_sizes) {
abort();
}
auto it = inputfile.entries.begin();
auto it_first_with_given_product_size = it;
while (it != inputfile.entries.end()) {
++it;
if (it == inputfile.entries.end() ||
it->product_size != it_first_with_given_product_size->product_size)
{
import_input_file_range_one_product_size(it_first_with_given_product_size, it);
it_first_with_given_product_size = it;
}
}
}
private:
void import_input_file_range_one_product_size(
const vector<inputfile_entry_t>::const_iterator& begin,
const vector<inputfile_entry_t>::const_iterator& end)
{
uint16_t product_size = begin->product_size;
float max_gflops = 0.0f;
for (auto it = begin; it != end; ++it) {
if (it->product_size != product_size) {
cerr << "Unexpected ordering of entries in " << filename << endl;
cerr << "(Expected all entries for product size " << hex << product_size << dec << " to be grouped)" << endl;
exit(1);
}
max_gflops = max(max_gflops, it->gflops);
}
for (auto it = begin; it != end; ++it) {
preprocessed_inputfile_entry_t entry;
entry.product_size = it->product_size;
entry.block_size = it->pot_block_size;
entry.efficiency = it->gflops / max_gflops;
entries.push_back(entry);
}
}
};
void check_all_files_in_same_exact_order(
const vector<preprocessed_inputfile_t>& preprocessed_inputfiles)
{
if (preprocessed_inputfiles.empty()) {
return;
}
const preprocessed_inputfile_t& first_file = preprocessed_inputfiles[0];
const size_t num_entries = first_file.entries.size();
for (size_t i = 0; i < preprocessed_inputfiles.size(); i++) {
if (preprocessed_inputfiles[i].entries.size() != num_entries) {
cerr << "these files have different number of entries: "
<< preprocessed_inputfiles[i].filename
<< " and "
<< first_file.filename
<< endl;
exit(1);
}
}
for (size_t entry_index = 0; entry_index < num_entries; entry_index++) {
const uint16_t entry_product_size = first_file.entries[entry_index].product_size;
const uint16_t entry_block_size = first_file.entries[entry_index].block_size;
for (size_t file_index = 0; file_index < preprocessed_inputfiles.size(); file_index++) {
const preprocessed_inputfile_t& cur_file = preprocessed_inputfiles[file_index];
if (cur_file.entries[entry_index].product_size != entry_product_size ||
cur_file.entries[entry_index].block_size != entry_block_size)
{
cerr << "entries not in same order between these files: "
<< first_file.filename
<< " and "
<< cur_file.filename
<< endl;
exit(1);
}
}
}
}
float efficiency_of_subset(
const vector<preprocessed_inputfile_t>& preprocessed_inputfiles,
const vector<size_t>& subset)
{
if (subset.size() <= 1) {
return 1.0f;
}
const preprocessed_inputfile_t& first_file = preprocessed_inputfiles[subset[0]];
const size_t num_entries = first_file.entries.size();
float efficiency = 1.0f;
size_t entry_index = 0;
size_t first_entry_index_with_this_product_size = 0;
uint16_t product_size = first_file.entries[0].product_size;
while (entry_index < num_entries) {
++entry_index;
if (entry_index == num_entries ||
first_file.entries[entry_index].product_size != product_size)
{
float efficiency_this_product_size = 0.0f;
for (size_t e = first_entry_index_with_this_product_size; e < entry_index; e++) {
float efficiency_this_entry = 1.0f;
for (auto i = subset.begin(); i != subset.end(); ++i) {
efficiency_this_entry = min(efficiency_this_entry, preprocessed_inputfiles[*i].entries[e].efficiency);
}
efficiency_this_product_size = max(efficiency_this_product_size, efficiency_this_entry);
}
efficiency = min(efficiency, efficiency_this_product_size);
if (entry_index < num_entries) {
first_entry_index_with_this_product_size = entry_index;
product_size = first_file.entries[entry_index].product_size;
}
}
}
return efficiency;
}
void dump_table_for_subset(
const vector<preprocessed_inputfile_t>& preprocessed_inputfiles,
const vector<size_t>& subset)
{
const preprocessed_inputfile_t& first_file = preprocessed_inputfiles[subset[0]];
const size_t num_entries = first_file.entries.size();
size_t entry_index = 0;
size_t first_entry_index_with_this_product_size = 0;
uint16_t product_size = first_file.entries[0].product_size;
size_t i = 0;
size_triple_t min_product_size(first_file.entries.front().product_size);
size_triple_t max_product_size(first_file.entries.back().product_size);
if (!min_product_size.is_cubic() || !max_product_size.is_cubic()) {
abort();
}
if (only_cubic_sizes) {
cerr << "Can't generate tables with --only-cubic-sizes." << endl;
abort();
}
cout << "struct LookupTable {" << endl;
cout << " static const size_t BaseSize = " << min_product_size.k << ";" << endl;
const size_t NumSizes = log2_pot(max_product_size.k / min_product_size.k) + 1;
const size_t TableSize = NumSizes * NumSizes * NumSizes;
cout << " static const size_t NumSizes = " << NumSizes << ";" << endl;
cout << " static const unsigned short* Data() {" << endl;
cout << " static const unsigned short data[" << TableSize << "] = {";
while (entry_index < num_entries) {
++entry_index;
if (entry_index == num_entries ||
first_file.entries[entry_index].product_size != product_size)
{
float best_efficiency_this_product_size = 0.0f;
uint16_t best_block_size_this_product_size = 0;
for (size_t e = first_entry_index_with_this_product_size; e < entry_index; e++) {
float efficiency_this_entry = 1.0f;
for (auto i = subset.begin(); i != subset.end(); ++i) {
efficiency_this_entry = min(efficiency_this_entry, preprocessed_inputfiles[*i].entries[e].efficiency);
}
if (efficiency_this_entry > best_efficiency_this_product_size) {
best_efficiency_this_product_size = efficiency_this_entry;
best_block_size_this_product_size = first_file.entries[e].block_size;
}
}
if ((i++) % NumSizes) {
cout << " ";
} else {
cout << endl << " ";
}
cout << "0x" << hex << best_block_size_this_product_size << dec;
if (entry_index < num_entries) {
cout << ",";
first_entry_index_with_this_product_size = entry_index;
product_size = first_file.entries[entry_index].product_size;
}
}
}
if (i != TableSize) {
cerr << endl << "Wrote " << i << " table entries, expected " << TableSize << endl;
abort();
}
cout << endl << " };" << endl;
cout << " return data;" << endl;
cout << " }" << endl;
cout << "};" << endl;
}
float efficiency_of_partition(
const vector<preprocessed_inputfile_t>& preprocessed_inputfiles,
const vector<vector<size_t>>& partition)
{
float efficiency = 1.0f;
for (auto s = partition.begin(); s != partition.end(); ++s) {
efficiency = min(efficiency, efficiency_of_subset(preprocessed_inputfiles, *s));
}
return efficiency;
}
void make_first_subset(size_t subset_size, vector<size_t>& out_subset, size_t set_size)
{
assert(subset_size >= 1 && subset_size <= set_size);
out_subset.resize(subset_size);
for (size_t i = 0; i < subset_size; i++) {
out_subset[i] = i;
}
}
bool is_last_subset(const vector<size_t>& subset, size_t set_size)
{
return subset[0] == set_size - subset.size();
}
void next_subset(vector<size_t>& inout_subset, size_t set_size)
{
if (is_last_subset(inout_subset, set_size)) {
cerr << "iterating past the last subset" << endl;
abort();
}
size_t i = 1;
while (inout_subset[inout_subset.size() - i] == set_size - i) {
i++;
assert(i <= inout_subset.size());
}
size_t first_index_to_change = inout_subset.size() - i;
inout_subset[first_index_to_change]++;
size_t p = inout_subset[first_index_to_change];
for (size_t j = first_index_to_change + 1; j < inout_subset.size(); j++) {
inout_subset[j] = ++p;
}
}
const size_t number_of_subsets_limit = 100;
const size_t always_search_subsets_of_size_at_least = 2;
bool is_number_of_subsets_feasible(size_t n, size_t p)
{
assert(n>0 && p>0 && p<=n);
uint64_t numerator = 1, denominator = 1;
for (size_t i = 0; i < p; i++) {
numerator *= n - i;
denominator *= i + 1;
if (numerator > denominator * number_of_subsets_limit) {
return false;
}
}
return true;
}
size_t max_feasible_subset_size(size_t n)
{
assert(n > 0);
const size_t minresult = min<size_t>(n-1, always_search_subsets_of_size_at_least);
for (size_t p = 1; p <= n - 1; p++) {
if (!is_number_of_subsets_feasible(n, p+1)) {
return max(p, minresult);
}
}
return n - 1;
}
void find_subset_with_efficiency_higher_than(
const vector<preprocessed_inputfile_t>& preprocessed_inputfiles,
float required_efficiency_to_beat,
vector<size_t>& inout_remainder,
vector<size_t>& out_subset)
{
out_subset.resize(0);
if (required_efficiency_to_beat >= 1.0f) {
cerr << "can't beat efficiency 1." << endl;
abort();
}
while (!inout_remainder.empty()) {
vector<size_t> candidate_indices(inout_remainder.size());
for (size_t i = 0; i < candidate_indices.size(); i++) {
candidate_indices[i] = i;
}
size_t candidate_indices_subset_size = max_feasible_subset_size(candidate_indices.size());
while (candidate_indices_subset_size >= 1) {
vector<size_t> candidate_indices_subset;
make_first_subset(candidate_indices_subset_size,
candidate_indices_subset,
candidate_indices.size());
vector<size_t> best_candidate_indices_subset;
float best_efficiency = 0.0f;
vector<size_t> trial_subset = out_subset;
trial_subset.resize(out_subset.size() + candidate_indices_subset_size);
while (true)
{
for (size_t i = 0; i < candidate_indices_subset_size; i++) {
trial_subset[out_subset.size() + i] = inout_remainder[candidate_indices_subset[i]];
}
float trial_efficiency = efficiency_of_subset(preprocessed_inputfiles, trial_subset);
if (trial_efficiency > best_efficiency) {
best_efficiency = trial_efficiency;
best_candidate_indices_subset = candidate_indices_subset;
}
if (is_last_subset(candidate_indices_subset, candidate_indices.size())) {
break;
}
next_subset(candidate_indices_subset, candidate_indices.size());
}
if (best_efficiency > required_efficiency_to_beat) {
for (size_t i = 0; i < best_candidate_indices_subset.size(); i++) {
candidate_indices[i] = candidate_indices[best_candidate_indices_subset[i]];
}
candidate_indices.resize(best_candidate_indices_subset.size());
}
candidate_indices_subset_size--;
}
size_t candidate_index = candidate_indices[0];
auto candidate_iterator = inout_remainder.begin() + candidate_index;
vector<size_t> trial_subset = out_subset;
trial_subset.push_back(*candidate_iterator);
float trial_efficiency = efficiency_of_subset(preprocessed_inputfiles, trial_subset);
if (trial_efficiency > required_efficiency_to_beat) {
out_subset.push_back(*candidate_iterator);
inout_remainder.erase(candidate_iterator);
} else {
break;
}
}
}
void find_partition_with_efficiency_higher_than(
const vector<preprocessed_inputfile_t>& preprocessed_inputfiles,
float required_efficiency_to_beat,
vector<vector<size_t>>& out_partition)
{
out_partition.resize(0);
vector<size_t> remainder;
for (size_t i = 0; i < preprocessed_inputfiles.size(); i++) {
remainder.push_back(i);
}
while (!remainder.empty()) {
vector<size_t> new_subset;
find_subset_with_efficiency_higher_than(
preprocessed_inputfiles,
required_efficiency_to_beat,
remainder,
new_subset);
out_partition.push_back(new_subset);
}
}
void print_partition(
const vector<preprocessed_inputfile_t>& preprocessed_inputfiles,
const vector<vector<size_t>>& partition)
{
float efficiency = efficiency_of_partition(preprocessed_inputfiles, partition);
cout << "Partition into " << partition.size() << " subsets for " << efficiency * 100.0f << "% efficiency" << endl;
for (auto subset = partition.begin(); subset != partition.end(); ++subset) {
cout << " Subset " << (subset - partition.begin())
<< ", efficiency " << efficiency_of_subset(preprocessed_inputfiles, *subset) * 100.0f << "%:"
<< endl;
for (auto file = subset->begin(); file != subset->end(); ++file) {
cout << " " << preprocessed_inputfiles[*file].filename << endl;
}
if (dump_tables) {
cout << " Table:" << endl;
dump_table_for_subset(preprocessed_inputfiles, *subset);
}
}
cout << endl;
}
struct action_t
{
virtual const char* invokation_name() const { abort(); return nullptr; }
virtual void run(const vector<string>&) const { abort(); }
virtual ~action_t() {}
};
struct partition_action_t : action_t
{
virtual const char* invokation_name() const override { return "partition"; }
virtual void run(const vector<string>& input_filenames) const override
{
vector<preprocessed_inputfile_t> preprocessed_inputfiles;
if (input_filenames.empty()) {
cerr << "The " << invokation_name() << " action needs a list of input files." << endl;
exit(1);
}
for (auto it = input_filenames.begin(); it != input_filenames.end(); ++it) {
inputfile_t inputfile(*it);
switch (inputfile.type) {
case inputfile_t::type_t::all_pot_sizes:
preprocessed_inputfiles.emplace_back(inputfile);
break;
case inputfile_t::type_t::default_sizes:
cerr << "The " << invokation_name() << " action only uses measurements for all pot sizes, and "
<< "has no use for " << *it << " which contains measurements for default sizes." << endl;
exit(1);
break;
default:
cerr << "Unrecognized input file: " << *it << endl;
exit(1);
}
}
check_all_files_in_same_exact_order(preprocessed_inputfiles);
float required_efficiency_to_beat = 0.0f;
vector<vector<vector<size_t>>> partitions;
cerr << "searching for partitions...\r" << flush;
while (true)
{
vector<vector<size_t>> partition;
find_partition_with_efficiency_higher_than(
preprocessed_inputfiles,
required_efficiency_to_beat,
partition);
float actual_efficiency = efficiency_of_partition(preprocessed_inputfiles, partition);
cerr << "partition " << preprocessed_inputfiles.size() << " files into " << partition.size()
<< " subsets for " << 100.0f * actual_efficiency
<< " % efficiency"
<< " \r" << flush;
partitions.push_back(partition);
if (partition.size() == preprocessed_inputfiles.size() || actual_efficiency == 1.0f) {
break;
}
required_efficiency_to_beat = actual_efficiency;
}
cerr << " " << endl;
while (true) {
bool repeat = false;
for (size_t i = 0; i < partitions.size() - 1; i++) {
if (partitions[i].size() >= partitions[i+1].size()) {
partitions.erase(partitions.begin() + i);
repeat = true;
break;
}
}
if (!repeat) {
break;
}
}
for (auto it = partitions.begin(); it != partitions.end(); ++it) {
print_partition(preprocessed_inputfiles, *it);
}
}
};
struct evaluate_defaults_action_t : action_t
{
struct results_entry_t {
uint16_t product_size;
size_triple_t default_block_size;
uint16_t best_pot_block_size;
float default_gflops;
float best_pot_gflops;
float default_efficiency;
};
friend ostream& operator<<(ostream& s, const results_entry_t& entry)
{
return s
<< "Product size " << size_triple_t(entry.product_size)
<< ": default block size " << entry.default_block_size
<< " -> " << entry.default_gflops
<< " GFlop/s = " << entry.default_efficiency * 100.0f << " %"
<< " of best POT block size " << size_triple_t(entry.best_pot_block_size)
<< " -> " << entry.best_pot_gflops
<< " GFlop/s" << dec;
}
static bool lower_efficiency(const results_entry_t& e1, const results_entry_t& e2) {
return e1.default_efficiency < e2.default_efficiency;
}
virtual const char* invokation_name() const override { return "evaluate-defaults"; }
void show_usage_and_exit() const
{
cerr << "usage: " << invokation_name() << " default-sizes-data all-pot-sizes-data" << endl;
cerr << "checks how well the performance with default sizes compares to the best "
<< "performance measured over all POT sizes." << endl;
exit(1);
}
virtual void run(const vector<string>& input_filenames) const override
{
if (input_filenames.size() != 2) {
show_usage_and_exit();
}
inputfile_t inputfile_default_sizes(input_filenames[0]);
inputfile_t inputfile_all_pot_sizes(input_filenames[1]);
if (inputfile_default_sizes.type != inputfile_t::type_t::default_sizes) {
cerr << inputfile_default_sizes.filename << " is not an input file with default sizes." << endl;
show_usage_and_exit();
}
if (inputfile_all_pot_sizes.type != inputfile_t::type_t::all_pot_sizes) {
cerr << inputfile_all_pot_sizes.filename << " is not an input file with all POT sizes." << endl;
show_usage_and_exit();
}
vector<results_entry_t> results;
vector<results_entry_t> cubic_results;
uint16_t product_size = 0;
auto it_all_pot_sizes = inputfile_all_pot_sizes.entries.begin();
for (auto it_default_sizes = inputfile_default_sizes.entries.begin();
it_default_sizes != inputfile_default_sizes.entries.end();
++it_default_sizes)
{
if (it_default_sizes->product_size == product_size) {
continue;
}
product_size = it_default_sizes->product_size;
while (it_all_pot_sizes != inputfile_all_pot_sizes.entries.end() &&
it_all_pot_sizes->product_size != product_size)
{
++it_all_pot_sizes;
}
if (it_all_pot_sizes == inputfile_all_pot_sizes.entries.end()) {
break;
}
uint16_t best_pot_block_size = 0;
float best_pot_gflops = 0;
for (auto it = it_all_pot_sizes;
it != inputfile_all_pot_sizes.entries.end() && it->product_size == product_size;
++it)
{
if (it->gflops > best_pot_gflops) {
best_pot_gflops = it->gflops;
best_pot_block_size = it->pot_block_size;
}
}
results_entry_t entry;
entry.product_size = product_size;
entry.default_block_size = it_default_sizes->nonpot_block_size;
entry.best_pot_block_size = best_pot_block_size;
entry.default_gflops = it_default_sizes->gflops;
entry.best_pot_gflops = best_pot_gflops;
entry.default_efficiency = entry.default_gflops / entry.best_pot_gflops;
results.push_back(entry);
size_triple_t t(product_size);
if (t.k == t.m && t.m == t.n) {
cubic_results.push_back(entry);
}
}
cout << "All results:" << endl;
for (auto it = results.begin(); it != results.end(); ++it) {
cout << *it << endl;
}
cout << endl;
sort(results.begin(), results.end(), lower_efficiency);
const size_t n = min<size_t>(20, results.size());
cout << n << " worst results:" << endl;
for (size_t i = 0; i < n; i++) {
cout << results[i] << endl;
}
cout << endl;
cout << "cubic results:" << endl;
for (auto it = cubic_results.begin(); it != cubic_results.end(); ++it) {
cout << *it << endl;
}
cout << endl;
sort(cubic_results.begin(), cubic_results.end(), lower_efficiency);
cout.precision(2);
vector<float> a = {0.5f, 0.20f, 0.10f, 0.05f, 0.02f, 0.01f};
for (auto it = a.begin(); it != a.end(); ++it) {
size_t n = min(results.size() - 1, size_t(*it * results.size()));
cout << (100.0f * n / (results.size() - 1))
<< " % of product sizes have default efficiency <= "
<< 100.0f * results[n].default_efficiency << " %" << endl;
}
cout.precision(default_precision);
}
};
void show_usage_and_exit(int argc, char* argv[],
const vector<unique_ptr<action_t>>& available_actions)
{
cerr << "usage: " << argv[0] << " <action> [options...] <input files...>" << endl;
cerr << "available actions:" << endl;
for (auto it = available_actions.begin(); it != available_actions.end(); ++it) {
cerr << " " << (*it)->invokation_name() << endl;
}
cerr << "the input files should each contain an output of benchmark-blocking-sizes" << endl;
exit(1);
}
int main(int argc, char* argv[])
{
cout.precision(default_precision);
cerr.precision(default_precision);
vector<unique_ptr<action_t>> available_actions;
available_actions.emplace_back(new partition_action_t);
available_actions.emplace_back(new evaluate_defaults_action_t);
vector<string> input_filenames;
action_t* action = nullptr;
if (argc < 2) {
show_usage_and_exit(argc, argv, available_actions);
}
for (int i = 1; i < argc; i++) {
bool arg_handled = false;
// Step 1. Try to match action invocation names.
for (auto it = available_actions.begin(); it != available_actions.end(); ++it) {
if (!strcmp(argv[i], (*it)->invokation_name())) {
if (!action) {
action = it->get();
arg_handled = true;
break;
} else {
cerr << "can't specify more than one action!" << endl;
show_usage_and_exit(argc, argv, available_actions);
}
}
}
if (arg_handled) {
continue;
}
// Step 2. Try to match option names.
if (argv[i][0] == '-') {
if (!strcmp(argv[i], "--only-cubic-sizes")) {
only_cubic_sizes = true;
arg_handled = true;
}
if (!strcmp(argv[i], "--dump-tables")) {
dump_tables = true;
arg_handled = true;
}
if (!arg_handled) {
cerr << "Unrecognized option: " << argv[i] << endl;
show_usage_and_exit(argc, argv, available_actions);
}
}
if (arg_handled) {
continue;
}
// Step 3. Default to interpreting args as input filenames.
input_filenames.emplace_back(argv[i]);
}
if (dump_tables && only_cubic_sizes) {
cerr << "Incompatible options: --only-cubic-sizes and --dump-tables." << endl;
show_usage_and_exit(argc, argv, available_actions);
}
if (!action) {
show_usage_and_exit(argc, argv, available_actions);
}
action->run(input_filenames);
}
@@ -0,0 +1,35 @@
#include <iostream>
#include "BenchUtil.h"
#include "basicbenchmark.h"
int main(int argc, char *argv[])
{
DISABLE_SSE_EXCEPTIONS();
// this is the list of matrix type and size we want to bench:
// ((suffix) (matrix size) (number of iterations))
#define MODES ((3d)(3)(4000000)) ((4d)(4)(1000000)) ((Xd)(4)(1000000)) ((Xd)(20)(10000))
// #define MODES ((Xd)(20)(10000))
#define _GENERATE_HEADER(R,ARG,EL) << BOOST_PP_STRINGIZE(BOOST_PP_SEQ_HEAD(EL)) << "-" \
<< BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(1,EL)) << "x" \
<< BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(1,EL)) << " / "
std::cout BOOST_PP_SEQ_FOR_EACH(_GENERATE_HEADER, ~, MODES ) << endl;
const int tries = 10;
#define _RUN_BENCH(R,ARG,EL) \
std::cout << ARG( \
BOOST_PP_CAT(Matrix, BOOST_PP_SEQ_HEAD(EL)) (\
BOOST_PP_SEQ_ELEM(1,EL),BOOST_PP_SEQ_ELEM(1,EL)), BOOST_PP_SEQ_ELEM(2,EL), tries) \
<< " ";
BOOST_PP_SEQ_FOR_EACH(_RUN_BENCH, benchBasic<LazyEval>, MODES );
std::cout << endl;
BOOST_PP_SEQ_FOR_EACH(_RUN_BENCH, benchBasic<EarlyEval>, MODES );
std::cout << endl;
return 0;
}
@@ -0,0 +1,63 @@
#ifndef EIGEN_BENCH_BASICBENCH_H
#define EIGEN_BENCH_BASICBENCH_H
enum {LazyEval, EarlyEval, OmpEval};
template<int Mode, typename MatrixType>
void benchBasic_loop(const MatrixType& I, MatrixType& m, int iterations) __attribute__((noinline));
template<int Mode, typename MatrixType>
void benchBasic_loop(const MatrixType& I, MatrixType& m, int iterations)
{
for(int a = 0; a < iterations; a++)
{
if (Mode==LazyEval)
{
asm("#begin_bench_loop LazyEval");
if (MatrixType::SizeAtCompileTime!=Eigen::Dynamic) asm("#fixedsize");
m = (I + 0.00005 * (m + m.lazyProduct(m))).eval();
}
else if (Mode==OmpEval)
{
asm("#begin_bench_loop OmpEval");
if (MatrixType::SizeAtCompileTime!=Eigen::Dynamic) asm("#fixedsize");
m = (I + 0.00005 * (m + m.lazyProduct(m))).eval();
}
else
{
asm("#begin_bench_loop EarlyEval");
if (MatrixType::SizeAtCompileTime!=Eigen::Dynamic) asm("#fixedsize");
m = I + 0.00005 * (m + m * m);
}
asm("#end_bench_loop");
}
}
template<int Mode, typename MatrixType>
double benchBasic(const MatrixType& mat, int size, int tries) __attribute__((noinline));
template<int Mode, typename MatrixType>
double benchBasic(const MatrixType& mat, int iterations, int tries)
{
const int rows = mat.rows();
const int cols = mat.cols();
MatrixType I(rows,cols);
MatrixType m(rows,cols);
initMatrix_identity(I);
Eigen::BenchTimer timer;
for(uint t=0; t<tries; ++t)
{
initMatrix_random(m);
timer.start();
benchBasic_loop<Mode>(I, m, iterations);
timer.stop();
cerr << m;
}
return timer.value();
};
#endif // EIGEN_BENCH_BASICBENCH_H
@@ -0,0 +1,219 @@
// g++ -O3 -DNDEBUG -I.. -L /usr/lib64/atlas/ benchBlasGemm.cpp -o benchBlasGemm -lrt -lcblas
// possible options:
// -DEIGEN_DONT_VECTORIZE
// -msse2
// #define EIGEN_DEFAULT_TO_ROW_MAJOR
#define _FLOAT
#include <iostream>
#include <Eigen/Core>
#include "BenchTimer.h"
// include the BLAS headers
extern "C" {
#include <cblas.h>
}
#include <string>
#ifdef _FLOAT
typedef float Scalar;
#define CBLAS_GEMM cblas_sgemm
#else
typedef double Scalar;
#define CBLAS_GEMM cblas_dgemm
#endif
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MyMatrix;
void bench_eigengemm(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops);
void check_product(int M, int N, int K);
void check_product(void);
int main(int argc, char *argv[])
{
// disable SSE exceptions
#ifdef __GNUC__
{
int aux;
asm(
"stmxcsr %[aux] \n\t"
"orl $32832, %[aux] \n\t"
"ldmxcsr %[aux] \n\t"
: : [aux] "m" (aux));
}
#endif
int nbtries=1, nbloops=1, M, N, K;
if (argc==2)
{
if (std::string(argv[1])=="check")
check_product();
else
M = N = K = atoi(argv[1]);
}
else if ((argc==3) && (std::string(argv[1])=="auto"))
{
M = N = K = atoi(argv[2]);
nbloops = 1000000000/(M*M*M);
if (nbloops<1)
nbloops = 1;
nbtries = 6;
}
else if (argc==4)
{
M = N = K = atoi(argv[1]);
nbloops = atoi(argv[2]);
nbtries = atoi(argv[3]);
}
else if (argc==6)
{
M = atoi(argv[1]);
N = atoi(argv[2]);
K = atoi(argv[3]);
nbloops = atoi(argv[4]);
nbtries = atoi(argv[5]);
}
else
{
std::cout << "Usage: " << argv[0] << " size \n";
std::cout << "Usage: " << argv[0] << " auto size\n";
std::cout << "Usage: " << argv[0] << " size nbloops nbtries\n";
std::cout << "Usage: " << argv[0] << " M N K nbloops nbtries\n";
std::cout << "Usage: " << argv[0] << " check\n";
std::cout << "Options:\n";
std::cout << " size unique size of the 2 matrices (integer)\n";
std::cout << " auto automatically set the number of repetitions and tries\n";
std::cout << " nbloops number of times the GEMM routines is executed\n";
std::cout << " nbtries number of times the loop is benched (return the best try)\n";
std::cout << " M N K sizes of the matrices: MxN = MxK * KxN (integers)\n";
std::cout << " check check eigen product using cblas as a reference\n";
exit(1);
}
double nbmad = double(M) * double(N) * double(K) * double(nbloops);
if (!(std::string(argv[1])=="auto"))
std::cout << M << " x " << N << " x " << K << "\n";
Scalar alpha, beta;
MyMatrix ma(M,K), mb(K,N), mc(M,N);
ma = MyMatrix::Random(M,K);
mb = MyMatrix::Random(K,N);
mc = MyMatrix::Random(M,N);
Eigen::BenchTimer timer;
// we simply compute c += a*b, so:
alpha = 1;
beta = 1;
// bench cblas
// ROWS_A, COLS_B, COLS_A, 1.0, A, COLS_A, B, COLS_B, 0.0, C, COLS_B);
if (!(std::string(argv[1])=="auto"))
{
timer.reset();
for (uint k=0 ; k<nbtries ; ++k)
{
timer.start();
for (uint j=0 ; j<nbloops ; ++j)
#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
CBLAS_GEMM(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, N, K, alpha, ma.data(), K, mb.data(), N, beta, mc.data(), N);
#else
CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasNoTrans, M, N, K, alpha, ma.data(), M, mb.data(), K, beta, mc.data(), M);
#endif
timer.stop();
}
if (!(std::string(argv[1])=="auto"))
std::cout << "cblas: " << timer.value() << " (" << 1e-3*floor(1e-6*nbmad/timer.value()) << " GFlops/s)\n";
else
std::cout << M << " : " << timer.value() << " ; " << 1e-3*floor(1e-6*nbmad/timer.value()) << "\n";
}
// clear
ma = MyMatrix::Random(M,K);
mb = MyMatrix::Random(K,N);
mc = MyMatrix::Random(M,N);
// eigen
// if (!(std::string(argv[1])=="auto"))
{
timer.reset();
for (uint k=0 ; k<nbtries ; ++k)
{
timer.start();
bench_eigengemm(mc, ma, mb, nbloops);
timer.stop();
}
if (!(std::string(argv[1])=="auto"))
std::cout << "eigen : " << timer.value() << " (" << 1e-3*floor(1e-6*nbmad/timer.value()) << " GFlops/s)\n";
else
std::cout << M << " : " << timer.value() << " ; " << 1e-3*floor(1e-6*nbmad/timer.value()) << "\n";
}
std::cout << "l1: " << Eigen::l1CacheSize() << std::endl;
std::cout << "l2: " << Eigen::l2CacheSize() << std::endl;
return 0;
}
using namespace Eigen;
void bench_eigengemm(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops)
{
for (uint j=0 ; j<nbloops ; ++j)
mc.noalias() += ma * mb;
}
#define MYVERIFY(A,M) if (!(A)) { \
std::cout << "FAIL: " << M << "\n"; \
}
void check_product(int M, int N, int K)
{
MyMatrix ma(M,K), mb(K,N), mc(M,N), maT(K,M), mbT(N,K), meigen(M,N), mref(M,N);
ma = MyMatrix::Random(M,K);
mb = MyMatrix::Random(K,N);
maT = ma.transpose();
mbT = mb.transpose();
mc = MyMatrix::Random(M,N);
MyMatrix::Scalar eps = 1e-4;
meigen = mref = mc;
CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasNoTrans, M, N, K, 1, ma.data(), M, mb.data(), K, 1, mref.data(), M);
meigen += ma * mb;
MYVERIFY(meigen.isApprox(mref, eps),". * .");
meigen = mref = mc;
CBLAS_GEMM(CblasColMajor, CblasTrans, CblasNoTrans, M, N, K, 1, maT.data(), K, mb.data(), K, 1, mref.data(), M);
meigen += maT.transpose() * mb;
MYVERIFY(meigen.isApprox(mref, eps),"T * .");
meigen = mref = mc;
CBLAS_GEMM(CblasColMajor, CblasTrans, CblasTrans, M, N, K, 1, maT.data(), K, mbT.data(), N, 1, mref.data(), M);
meigen += (maT.transpose()) * (mbT.transpose());
MYVERIFY(meigen.isApprox(mref, eps),"T * T");
meigen = mref = mc;
CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasTrans, M, N, K, 1, ma.data(), M, mbT.data(), N, 1, mref.data(), M);
meigen += ma * mbT.transpose();
MYVERIFY(meigen.isApprox(mref, eps),". * T");
}
void check_product(void)
{
int M, N, K;
for (uint i=0; i<1000; ++i)
{
M = internal::random<int>(1,64);
N = internal::random<int>(1,768);
K = internal::random<int>(1,768);
M = (0 + M) * 1;
std::cout << M << " x " << N << " x " << K << "\n";
check_product(M, N, K);
}
}
@@ -0,0 +1,141 @@
// g++ -DNDEBUG -O3 -I.. benchCholesky.cpp -o benchCholesky && ./benchCholesky
// options:
// -DBENCH_GSL -lgsl /usr/lib/libcblas.so.3
// -DEIGEN_DONT_VECTORIZE
// -msse2
// -DREPEAT=100
// -DTRIES=10
// -DSCALAR=double
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Cholesky>
#include <bench/BenchUtil.h>
using namespace Eigen;
#ifndef REPEAT
#define REPEAT 10000
#endif
#ifndef TRIES
#define TRIES 10
#endif
typedef float Scalar;
template <typename MatrixType>
__attribute__ ((noinline)) void benchLLT(const MatrixType& m)
{
int rows = m.rows();
int cols = m.cols();
double cost = 0;
for (int j=0; j<rows; ++j)
{
int r = std::max(rows - j -1,0);
cost += 2*(r*j+r+j);
}
int repeats = (REPEAT*1000)/(rows*rows);
typedef typename MatrixType::Scalar Scalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
MatrixType a = MatrixType::Random(rows,cols);
SquareMatrixType covMat = a * a.adjoint();
BenchTimer timerNoSqrt, timerSqrt;
Scalar acc = 0;
int r = internal::random<int>(0,covMat.rows()-1);
int c = internal::random<int>(0,covMat.cols()-1);
for (int t=0; t<TRIES; ++t)
{
timerNoSqrt.start();
for (int k=0; k<repeats; ++k)
{
LDLT<SquareMatrixType> cholnosqrt(covMat);
acc += cholnosqrt.matrixL().coeff(r,c);
}
timerNoSqrt.stop();
}
for (int t=0; t<TRIES; ++t)
{
timerSqrt.start();
for (int k=0; k<repeats; ++k)
{
LLT<SquareMatrixType> chol(covMat);
acc += chol.matrixL().coeff(r,c);
}
timerSqrt.stop();
}
if (MatrixType::RowsAtCompileTime==Dynamic)
std::cout << "dyn ";
else
std::cout << "fixed ";
std::cout << covMat.rows() << " \t"
<< (timerNoSqrt.best()) / repeats << "s "
<< "(" << 1e-9 * cost*repeats/timerNoSqrt.best() << " GFLOPS)\t"
<< (timerSqrt.best()) / repeats << "s "
<< "(" << 1e-9 * cost*repeats/timerSqrt.best() << " GFLOPS)\n";
#ifdef BENCH_GSL
if (MatrixType::RowsAtCompileTime==Dynamic)
{
timerSqrt.reset();
gsl_matrix* gslCovMat = gsl_matrix_alloc(covMat.rows(),covMat.cols());
gsl_matrix* gslCopy = gsl_matrix_alloc(covMat.rows(),covMat.cols());
eiToGsl(covMat, &gslCovMat);
for (int t=0; t<TRIES; ++t)
{
timerSqrt.start();
for (int k=0; k<repeats; ++k)
{
gsl_matrix_memcpy(gslCopy,gslCovMat);
gsl_linalg_cholesky_decomp(gslCopy);
acc += gsl_matrix_get(gslCopy,r,c);
}
timerSqrt.stop();
}
std::cout << " | \t"
<< timerSqrt.value() * REPEAT / repeats << "s";
gsl_matrix_free(gslCovMat);
}
#endif
std::cout << "\n";
// make sure the compiler does not optimize too much
if (acc==123)
std::cout << acc;
}
int main(int argc, char* argv[])
{
const int dynsizes[] = {4,6,8,16,24,32,49,64,128,256,512,900,1500,0};
std::cout << "size LDLT LLT";
// #ifdef BENCH_GSL
// std::cout << " GSL (standard + double + ATLAS) ";
// #endif
std::cout << "\n";
for (int i=0; dynsizes[i]>0; ++i)
benchLLT(Matrix<Scalar,Dynamic,Dynamic>(dynsizes[i],dynsizes[i]));
benchLLT(Matrix<Scalar,2,2>());
benchLLT(Matrix<Scalar,3,3>());
benchLLT(Matrix<Scalar,4,4>());
benchLLT(Matrix<Scalar,5,5>());
benchLLT(Matrix<Scalar,6,6>());
benchLLT(Matrix<Scalar,7,7>());
benchLLT(Matrix<Scalar,8,8>());
benchLLT(Matrix<Scalar,12,12>());
benchLLT(Matrix<Scalar,16,16>());
return 0;
}
@@ -0,0 +1,212 @@
// g++ -DNDEBUG -O3 -I.. benchEigenSolver.cpp -o benchEigenSolver && ./benchEigenSolver
// options:
// -DBENCH_GMM
// -DBENCH_GSL -lgsl /usr/lib/libcblas.so.3
// -DEIGEN_DONT_VECTORIZE
// -msse2
// -DREPEAT=100
// -DTRIES=10
// -DSCALAR=double
#include <iostream>
#include <Eigen/Core>
#include <Eigen/QR>
#include <bench/BenchUtil.h>
using namespace Eigen;
#ifndef REPEAT
#define REPEAT 1000
#endif
#ifndef TRIES
#define TRIES 4
#endif
#ifndef SCALAR
#define SCALAR float
#endif
typedef SCALAR Scalar;
template <typename MatrixType>
__attribute__ ((noinline)) void benchEigenSolver(const MatrixType& m)
{
int rows = m.rows();
int cols = m.cols();
int stdRepeats = std::max(1,int((REPEAT*1000)/(rows*rows*sqrt(rows))));
int saRepeats = stdRepeats * 4;
typedef typename MatrixType::Scalar Scalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
MatrixType a = MatrixType::Random(rows,cols);
SquareMatrixType covMat = a * a.adjoint();
BenchTimer timerSa, timerStd;
Scalar acc = 0;
int r = internal::random<int>(0,covMat.rows()-1);
int c = internal::random<int>(0,covMat.cols()-1);
{
SelfAdjointEigenSolver<SquareMatrixType> ei(covMat);
for (int t=0; t<TRIES; ++t)
{
timerSa.start();
for (int k=0; k<saRepeats; ++k)
{
ei.compute(covMat);
acc += ei.eigenvectors().coeff(r,c);
}
timerSa.stop();
}
}
{
EigenSolver<SquareMatrixType> ei(covMat);
for (int t=0; t<TRIES; ++t)
{
timerStd.start();
for (int k=0; k<stdRepeats; ++k)
{
ei.compute(covMat);
acc += ei.eigenvectors().coeff(r,c);
}
timerStd.stop();
}
}
if (MatrixType::RowsAtCompileTime==Dynamic)
std::cout << "dyn ";
else
std::cout << "fixed ";
std::cout << covMat.rows() << " \t"
<< timerSa.value() * REPEAT / saRepeats << "s \t"
<< timerStd.value() * REPEAT / stdRepeats << "s";
#ifdef BENCH_GMM
if (MatrixType::RowsAtCompileTime==Dynamic)
{
timerSa.reset();
timerStd.reset();
gmm::dense_matrix<Scalar> gmmCovMat(covMat.rows(),covMat.cols());
gmm::dense_matrix<Scalar> eigvect(covMat.rows(),covMat.cols());
std::vector<Scalar> eigval(covMat.rows());
eiToGmm(covMat, gmmCovMat);
for (int t=0; t<TRIES; ++t)
{
timerSa.start();
for (int k=0; k<saRepeats; ++k)
{
gmm::symmetric_qr_algorithm(gmmCovMat, eigval, eigvect);
acc += eigvect(r,c);
}
timerSa.stop();
}
// the non-selfadjoint solver does not compute the eigen vectors
// for (int t=0; t<TRIES; ++t)
// {
// timerStd.start();
// for (int k=0; k<stdRepeats; ++k)
// {
// gmm::implicit_qr_algorithm(gmmCovMat, eigval, eigvect);
// acc += eigvect(r,c);
// }
// timerStd.stop();
// }
std::cout << " | \t"
<< timerSa.value() * REPEAT / saRepeats << "s"
<< /*timerStd.value() * REPEAT / stdRepeats << "s"*/ " na ";
}
#endif
#ifdef BENCH_GSL
if (MatrixType::RowsAtCompileTime==Dynamic)
{
timerSa.reset();
timerStd.reset();
gsl_matrix* gslCovMat = gsl_matrix_alloc(covMat.rows(),covMat.cols());
gsl_matrix* gslCopy = gsl_matrix_alloc(covMat.rows(),covMat.cols());
gsl_matrix* eigvect = gsl_matrix_alloc(covMat.rows(),covMat.cols());
gsl_vector* eigval = gsl_vector_alloc(covMat.rows());
gsl_eigen_symmv_workspace* eisymm = gsl_eigen_symmv_alloc(covMat.rows());
gsl_matrix_complex* eigvectz = gsl_matrix_complex_alloc(covMat.rows(),covMat.cols());
gsl_vector_complex* eigvalz = gsl_vector_complex_alloc(covMat.rows());
gsl_eigen_nonsymmv_workspace* einonsymm = gsl_eigen_nonsymmv_alloc(covMat.rows());
eiToGsl(covMat, &gslCovMat);
for (int t=0; t<TRIES; ++t)
{
timerSa.start();
for (int k=0; k<saRepeats; ++k)
{
gsl_matrix_memcpy(gslCopy,gslCovMat);
gsl_eigen_symmv(gslCopy, eigval, eigvect, eisymm);
acc += gsl_matrix_get(eigvect,r,c);
}
timerSa.stop();
}
for (int t=0; t<TRIES; ++t)
{
timerStd.start();
for (int k=0; k<stdRepeats; ++k)
{
gsl_matrix_memcpy(gslCopy,gslCovMat);
gsl_eigen_nonsymmv(gslCopy, eigvalz, eigvectz, einonsymm);
acc += GSL_REAL(gsl_matrix_complex_get(eigvectz,r,c));
}
timerStd.stop();
}
std::cout << " | \t"
<< timerSa.value() * REPEAT / saRepeats << "s \t"
<< timerStd.value() * REPEAT / stdRepeats << "s";
gsl_matrix_free(gslCovMat);
gsl_vector_free(gslCopy);
gsl_matrix_free(eigvect);
gsl_vector_free(eigval);
gsl_matrix_complex_free(eigvectz);
gsl_vector_complex_free(eigvalz);
gsl_eigen_symmv_free(eisymm);
gsl_eigen_nonsymmv_free(einonsymm);
}
#endif
std::cout << "\n";
// make sure the compiler does not optimize too much
if (acc==123)
std::cout << acc;
}
int main(int argc, char* argv[])
{
const int dynsizes[] = {4,6,8,12,16,24,32,64,128,256,512,0};
std::cout << "size selfadjoint generic";
#ifdef BENCH_GMM
std::cout << " GMM++ ";
#endif
#ifdef BENCH_GSL
std::cout << " GSL (double + ATLAS) ";
#endif
std::cout << "\n";
for (uint i=0; dynsizes[i]>0; ++i)
benchEigenSolver(Matrix<Scalar,Dynamic,Dynamic>(dynsizes[i],dynsizes[i]));
benchEigenSolver(Matrix<Scalar,2,2>());
benchEigenSolver(Matrix<Scalar,3,3>());
benchEigenSolver(Matrix<Scalar,4,4>());
benchEigenSolver(Matrix<Scalar,6,6>());
benchEigenSolver(Matrix<Scalar,8,8>());
benchEigenSolver(Matrix<Scalar,12,12>());
benchEigenSolver(Matrix<Scalar,16,16>());
return 0;
}
@@ -0,0 +1,115 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Mark Borgerding mark a borgerding net
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <iostream>
#include <bench/BenchUtil.h>
#include <complex>
#include <vector>
#include <Eigen/Core>
#include <unsupported/Eigen/FFT>
using namespace Eigen;
using namespace std;
template <typename T>
string nameof();
template <> string nameof<float>() {return "float";}
template <> string nameof<double>() {return "double";}
template <> string nameof<long double>() {return "long double";}
#ifndef TYPE
#define TYPE float
#endif
#ifndef NFFT
#define NFFT 1024
#endif
#ifndef NDATA
#define NDATA 1000000
#endif
using namespace Eigen;
template <typename T>
void bench(int nfft,bool fwd,bool unscaled=false, bool halfspec=false)
{
typedef typename NumTraits<T>::Real Scalar;
typedef typename std::complex<Scalar> Complex;
int nits = NDATA/nfft;
vector<T> inbuf(nfft);
vector<Complex > outbuf(nfft);
FFT< Scalar > fft;
if (unscaled) {
fft.SetFlag(fft.Unscaled);
cout << "unscaled ";
}
if (halfspec) {
fft.SetFlag(fft.HalfSpectrum);
cout << "halfspec ";
}
std::fill(inbuf.begin(),inbuf.end(),0);
fft.fwd( outbuf , inbuf);
BenchTimer timer;
timer.reset();
for (int k=0;k<8;++k) {
timer.start();
if (fwd)
for(int i = 0; i < nits; i++)
fft.fwd( outbuf , inbuf);
else
for(int i = 0; i < nits; i++)
fft.inv(inbuf,outbuf);
timer.stop();
}
cout << nameof<Scalar>() << " ";
double mflops = 5.*nfft*log2((double)nfft) / (1e6 * timer.value() / (double)nits );
if ( NumTraits<T>::IsComplex ) {
cout << "complex";
}else{
cout << "real ";
mflops /= 2;
}
if (fwd)
cout << " fwd";
else
cout << " inv";
cout << " NFFT=" << nfft << " " << (double(1e-6*nfft*nits)/timer.value()) << " MS/s " << mflops << "MFLOPS\n";
}
int main(int argc,char ** argv)
{
bench<complex<float> >(NFFT,true);
bench<complex<float> >(NFFT,false);
bench<float>(NFFT,true);
bench<float>(NFFT,false);
bench<float>(NFFT,false,true);
bench<float>(NFFT,false,true,true);
bench<complex<double> >(NFFT,true);
bench<complex<double> >(NFFT,false);
bench<double>(NFFT,true);
bench<double>(NFFT,false);
bench<complex<long double> >(NFFT,true);
bench<complex<long double> >(NFFT,false);
bench<long double>(NFFT,true);
bench<long double>(NFFT,false);
return 0;
}
@@ -0,0 +1,134 @@
#include <iostream>
#include <iomanip>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>
using namespace Eigen;
using namespace std;
#ifndef REPEAT
#define REPEAT 1000000
#endif
enum func_opt
{
TV,
TMATV,
TMATVMAT,
};
template <class res, class arg1, class arg2, int opt>
struct func;
template <class res, class arg1, class arg2>
struct func<res, arg1, arg2, TV>
{
static EIGEN_DONT_INLINE res run( arg1& a1, arg2& a2 )
{
asm ("");
return a1 * a2;
}
};
template <class res, class arg1, class arg2>
struct func<res, arg1, arg2, TMATV>
{
static EIGEN_DONT_INLINE res run( arg1& a1, arg2& a2 )
{
asm ("");
return a1.matrix() * a2;
}
};
template <class res, class arg1, class arg2>
struct func<res, arg1, arg2, TMATVMAT>
{
static EIGEN_DONT_INLINE res run( arg1& a1, arg2& a2 )
{
asm ("");
return res(a1.matrix() * a2.matrix());
}
};
template <class func, class arg1, class arg2>
struct test_transform
{
static void run()
{
arg1 a1;
a1.setIdentity();
arg2 a2;
a2.setIdentity();
BenchTimer timer;
timer.reset();
for (int k=0; k<10; ++k)
{
timer.start();
for (int k=0; k<REPEAT; ++k)
a2 = func::run( a1, a2 );
timer.stop();
}
cout << setprecision(4) << fixed << timer.value() << "s " << endl;;
}
};
#define run_vec( op, scalar, mode, option, vsize ) \
std::cout << #scalar << "\t " << #mode << "\t " << #option << " " << #vsize " "; \
{\
typedef Transform<scalar, 3, mode, option> Trans;\
typedef Matrix<scalar, vsize, 1, option> Vec;\
typedef func<Vec,Trans,Vec,op> Func;\
test_transform< Func, Trans, Vec >::run();\
}
#define run_trans( op, scalar, mode, option ) \
std::cout << #scalar << "\t " << #mode << "\t " << #option << " "; \
{\
typedef Transform<scalar, 3, mode, option> Trans;\
typedef func<Trans,Trans,Trans,op> Func;\
test_transform< Func, Trans, Trans >::run();\
}
int main(int argc, char* argv[])
{
cout << "vec = trans * vec" << endl;
run_vec(TV, float, Isometry, AutoAlign, 3);
run_vec(TV, float, Isometry, DontAlign, 3);
run_vec(TV, float, Isometry, AutoAlign, 4);
run_vec(TV, float, Isometry, DontAlign, 4);
run_vec(TV, float, Projective, AutoAlign, 4);
run_vec(TV, float, Projective, DontAlign, 4);
run_vec(TV, double, Isometry, AutoAlign, 3);
run_vec(TV, double, Isometry, DontAlign, 3);
run_vec(TV, double, Isometry, AutoAlign, 4);
run_vec(TV, double, Isometry, DontAlign, 4);
run_vec(TV, double, Projective, AutoAlign, 4);
run_vec(TV, double, Projective, DontAlign, 4);
cout << "vec = trans.matrix() * vec" << endl;
run_vec(TMATV, float, Isometry, AutoAlign, 4);
run_vec(TMATV, float, Isometry, DontAlign, 4);
run_vec(TMATV, double, Isometry, AutoAlign, 4);
run_vec(TMATV, double, Isometry, DontAlign, 4);
cout << "trans = trans1 * trans" << endl;
run_trans(TV, float, Isometry, AutoAlign);
run_trans(TV, float, Isometry, DontAlign);
run_trans(TV, double, Isometry, AutoAlign);
run_trans(TV, double, Isometry, DontAlign);
run_trans(TV, float, Projective, AutoAlign);
run_trans(TV, float, Projective, DontAlign);
run_trans(TV, double, Projective, AutoAlign);
run_trans(TV, double, Projective, DontAlign);
cout << "trans = trans1.matrix() * trans.matrix()" << endl;
run_trans(TMATVMAT, float, Isometry, AutoAlign);
run_trans(TMATVMAT, float, Isometry, DontAlign);
run_trans(TMATVMAT, double, Isometry, AutoAlign);
run_trans(TMATVMAT, double, Isometry, DontAlign);
}
@@ -0,0 +1,135 @@
#include <iostream>
#include <Eigen/Core>
#include <bench/BenchTimer.h>
using namespace Eigen;
#ifndef SIZE
#define SIZE 50
#endif
#ifndef REPEAT
#define REPEAT 10000
#endif
typedef float Scalar;
__attribute__ ((noinline)) void benchVec(Scalar* a, Scalar* b, Scalar* c, int size);
__attribute__ ((noinline)) void benchVec(MatrixXf& a, MatrixXf& b, MatrixXf& c);
__attribute__ ((noinline)) void benchVec(VectorXf& a, VectorXf& b, VectorXf& c);
int main(int argc, char* argv[])
{
int size = SIZE * 8;
int size2 = size * size;
Scalar* a = internal::aligned_new<Scalar>(size2);
Scalar* b = internal::aligned_new<Scalar>(size2+4)+1;
Scalar* c = internal::aligned_new<Scalar>(size2);
for (int i=0; i<size; ++i)
{
a[i] = b[i] = c[i] = 0;
}
BenchTimer timer;
timer.reset();
for (int k=0; k<10; ++k)
{
timer.start();
benchVec(a, b, c, size2);
timer.stop();
}
std::cout << timer.value() << "s " << (double(size2*REPEAT)/timer.value())/(1024.*1024.*1024.) << " GFlops\n";
return 0;
for (int innersize = size; innersize>2 ; --innersize)
{
if (size2%innersize==0)
{
int outersize = size2/innersize;
MatrixXf ma = Map<MatrixXf>(a, innersize, outersize );
MatrixXf mb = Map<MatrixXf>(b, innersize, outersize );
MatrixXf mc = Map<MatrixXf>(c, innersize, outersize );
timer.reset();
for (int k=0; k<3; ++k)
{
timer.start();
benchVec(ma, mb, mc);
timer.stop();
}
std::cout << innersize << " x " << outersize << " " << timer.value() << "s " << (double(size2*REPEAT)/timer.value())/(1024.*1024.*1024.) << " GFlops\n";
}
}
VectorXf va = Map<VectorXf>(a, size2);
VectorXf vb = Map<VectorXf>(b, size2);
VectorXf vc = Map<VectorXf>(c, size2);
timer.reset();
for (int k=0; k<3; ++k)
{
timer.start();
benchVec(va, vb, vc);
timer.stop();
}
std::cout << timer.value() << "s " << (double(size2*REPEAT)/timer.value())/(1024.*1024.*1024.) << " GFlops\n";
return 0;
}
void benchVec(MatrixXf& a, MatrixXf& b, MatrixXf& c)
{
for (int k=0; k<REPEAT; ++k)
a = a + b;
}
void benchVec(VectorXf& a, VectorXf& b, VectorXf& c)
{
for (int k=0; k<REPEAT; ++k)
a = a + b;
}
void benchVec(Scalar* a, Scalar* b, Scalar* c, int size)
{
typedef internal::packet_traits<Scalar>::type PacketScalar;
const int PacketSize = internal::packet_traits<Scalar>::size;
PacketScalar a0, a1, a2, a3, b0, b1, b2, b3;
for (int k=0; k<REPEAT; ++k)
for (int i=0; i<size; i+=PacketSize*8)
{
// a0 = internal::pload(&a[i]);
// b0 = internal::pload(&b[i]);
// a1 = internal::pload(&a[i+1*PacketSize]);
// b1 = internal::pload(&b[i+1*PacketSize]);
// a2 = internal::pload(&a[i+2*PacketSize]);
// b2 = internal::pload(&b[i+2*PacketSize]);
// a3 = internal::pload(&a[i+3*PacketSize]);
// b3 = internal::pload(&b[i+3*PacketSize]);
// internal::pstore(&a[i], internal::padd(a0, b0));
// a0 = internal::pload(&a[i+4*PacketSize]);
// b0 = internal::pload(&b[i+4*PacketSize]);
//
// internal::pstore(&a[i+1*PacketSize], internal::padd(a1, b1));
// a1 = internal::pload(&a[i+5*PacketSize]);
// b1 = internal::pload(&b[i+5*PacketSize]);
//
// internal::pstore(&a[i+2*PacketSize], internal::padd(a2, b2));
// a2 = internal::pload(&a[i+6*PacketSize]);
// b2 = internal::pload(&b[i+6*PacketSize]);
//
// internal::pstore(&a[i+3*PacketSize], internal::padd(a3, b3));
// a3 = internal::pload(&a[i+7*PacketSize]);
// b3 = internal::pload(&b[i+7*PacketSize]);
//
// internal::pstore(&a[i+4*PacketSize], internal::padd(a0, b0));
// internal::pstore(&a[i+5*PacketSize], internal::padd(a1, b1));
// internal::pstore(&a[i+6*PacketSize], internal::padd(a2, b2));
// internal::pstore(&a[i+7*PacketSize], internal::padd(a3, b3));
internal::pstore(&a[i+2*PacketSize], internal::padd(internal::ploadu(&a[i+2*PacketSize]), internal::ploadu(&b[i+2*PacketSize])));
internal::pstore(&a[i+3*PacketSize], internal::padd(internal::ploadu(&a[i+3*PacketSize]), internal::ploadu(&b[i+3*PacketSize])));
internal::pstore(&a[i+4*PacketSize], internal::padd(internal::ploadu(&a[i+4*PacketSize]), internal::ploadu(&b[i+4*PacketSize])));
internal::pstore(&a[i+5*PacketSize], internal::padd(internal::ploadu(&a[i+5*PacketSize]), internal::ploadu(&b[i+5*PacketSize])));
internal::pstore(&a[i+6*PacketSize], internal::padd(internal::ploadu(&a[i+6*PacketSize]), internal::ploadu(&b[i+6*PacketSize])));
internal::pstore(&a[i+7*PacketSize], internal::padd(internal::ploadu(&a[i+7*PacketSize]), internal::ploadu(&b[i+7*PacketSize])));
}
}
@@ -0,0 +1,375 @@
// g++-4.4 bench_gemm.cpp -I .. -O2 -DNDEBUG -lrt -fopenmp && OMP_NUM_THREADS=2 ./a.out
// icpc bench_gemm.cpp -I .. -O3 -DNDEBUG -lrt -openmp && OMP_NUM_THREADS=2 ./a.out
// Compilation options:
//
// -DSCALAR=std::complex<double>
// -DSCALARA=double or -DSCALARB=double
// -DHAVE_BLAS
// -DDECOUPLED
//
#include <iostream>
#include <bench/BenchTimer.h>
#include <Eigen/Core>
using namespace std;
using namespace Eigen;
#ifndef SCALAR
// #define SCALAR std::complex<float>
#define SCALAR float
#endif
#ifndef SCALARA
#define SCALARA SCALAR
#endif
#ifndef SCALARB
#define SCALARB SCALAR
#endif
#ifdef ROWMAJ_A
const int opt_A = RowMajor;
#else
const int opt_A = ColMajor;
#endif
#ifdef ROWMAJ_B
const int opt_B = RowMajor;
#else
const int opt_B = ColMajor;
#endif
typedef SCALAR Scalar;
typedef NumTraits<Scalar>::Real RealScalar;
typedef Matrix<SCALARA,Dynamic,Dynamic,opt_A> A;
typedef Matrix<SCALARB,Dynamic,Dynamic,opt_B> B;
typedef Matrix<Scalar,Dynamic,Dynamic> C;
typedef Matrix<RealScalar,Dynamic,Dynamic> M;
#ifdef HAVE_BLAS
extern "C" {
#include <Eigen/src/misc/blas.h>
}
static float fone = 1;
static float fzero = 0;
static double done = 1;
static double szero = 0;
static std::complex<float> cfone = 1;
static std::complex<float> cfzero = 0;
static std::complex<double> cdone = 1;
static std::complex<double> cdzero = 0;
static char notrans = 'N';
static char trans = 'T';
static char nonunit = 'N';
static char lower = 'L';
static char right = 'R';
static int intone = 1;
#ifdef ROWMAJ_A
const char transA = trans;
#else
const char transA = notrans;
#endif
#ifdef ROWMAJ_B
const char transB = trans;
#else
const char transB = notrans;
#endif
template<typename A,typename B>
void blas_gemm(const A& a, const B& b, MatrixXf& c)
{
int M = c.rows(); int N = c.cols(); int K = a.cols();
int lda = a.outerStride(); int ldb = b.outerStride(); int ldc = c.rows();
sgemm_(&transA,&transB,&M,&N,&K,&fone,
const_cast<float*>(a.data()),&lda,
const_cast<float*>(b.data()),&ldb,&fone,
c.data(),&ldc);
}
template<typename A,typename B>
void blas_gemm(const A& a, const B& b, MatrixXd& c)
{
int M = c.rows(); int N = c.cols(); int K = a.cols();
int lda = a.outerStride(); int ldb = b.outerStride(); int ldc = c.rows();
dgemm_(&transA,&transB,&M,&N,&K,&done,
const_cast<double*>(a.data()),&lda,
const_cast<double*>(b.data()),&ldb,&done,
c.data(),&ldc);
}
template<typename A,typename B>
void blas_gemm(const A& a, const B& b, MatrixXcf& c)
{
int M = c.rows(); int N = c.cols(); int K = a.cols();
int lda = a.outerStride(); int ldb = b.outerStride(); int ldc = c.rows();
cgemm_(&transA,&transB,&M,&N,&K,(float*)&cfone,
const_cast<float*>((const float*)a.data()),&lda,
const_cast<float*>((const float*)b.data()),&ldb,(float*)&cfone,
(float*)c.data(),&ldc);
}
template<typename A,typename B>
void blas_gemm(const A& a, const B& b, MatrixXcd& c)
{
int M = c.rows(); int N = c.cols(); int K = a.cols();
int lda = a.outerStride(); int ldb = b.outerStride(); int ldc = c.rows();
zgemm_(&transA,&transB,&M,&N,&K,(double*)&cdone,
const_cast<double*>((const double*)a.data()),&lda,
const_cast<double*>((const double*)b.data()),&ldb,(double*)&cdone,
(double*)c.data(),&ldc);
}
#endif
void matlab_cplx_cplx(const M& ar, const M& ai, const M& br, const M& bi, M& cr, M& ci)
{
cr.noalias() += ar * br;
cr.noalias() -= ai * bi;
ci.noalias() += ar * bi;
ci.noalias() += ai * br;
// [cr ci] += [ar ai] * br + [-ai ar] * bi
}
void matlab_real_cplx(const M& a, const M& br, const M& bi, M& cr, M& ci)
{
cr.noalias() += a * br;
ci.noalias() += a * bi;
}
void matlab_cplx_real(const M& ar, const M& ai, const M& b, M& cr, M& ci)
{
cr.noalias() += ar * b;
ci.noalias() += ai * b;
}
template<typename A, typename B, typename C>
EIGEN_DONT_INLINE void gemm(const A& a, const B& b, C& c)
{
c.noalias() += a * b;
}
int main(int argc, char ** argv)
{
std::ptrdiff_t l1 = internal::queryL1CacheSize();
std::ptrdiff_t l2 = internal::queryTopLevelCacheSize();
std::cout << "L1 cache size = " << (l1>0 ? l1/1024 : -1) << " KB\n";
std::cout << "L2/L3 cache size = " << (l2>0 ? l2/1024 : -1) << " KB\n";
typedef internal::gebp_traits<Scalar,Scalar> Traits;
std::cout << "Register blocking = " << Traits::mr << " x " << Traits::nr << "\n";
int rep = 1; // number of repetitions per try
int tries = 2; // number of tries, we keep the best
int s = 2048;
int m = s;
int n = s;
int p = s;
int cache_size1=-1, cache_size2=l2, cache_size3 = 0;
bool need_help = false;
for (int i=1; i<argc;)
{
if(argv[i][0]=='-')
{
if(argv[i][1]=='s')
{
++i;
s = atoi(argv[i++]);
m = n = p = s;
if(argv[i][0]!='-')
{
n = atoi(argv[i++]);
p = atoi(argv[i++]);
}
}
else if(argv[i][1]=='c')
{
++i;
cache_size1 = atoi(argv[i++]);
if(argv[i][0]!='-')
{
cache_size2 = atoi(argv[i++]);
if(argv[i][0]!='-')
cache_size3 = atoi(argv[i++]);
}
}
else if(argv[i][1]=='t')
{
tries = atoi(argv[++i]);
++i;
}
else if(argv[i][1]=='p')
{
++i;
rep = atoi(argv[i++]);
}
}
else
{
need_help = true;
break;
}
}
if(need_help)
{
std::cout << argv[0] << " -s <matrix sizes> -c <cache sizes> -t <nb tries> -p <nb repeats>\n";
std::cout << " <matrix sizes> : size\n";
std::cout << " <matrix sizes> : rows columns depth\n";
return 1;
}
#if EIGEN_VERSION_AT_LEAST(3,2,90)
if(cache_size1>0)
setCpuCacheSizes(cache_size1,cache_size2,cache_size3);
#endif
A a(m,p); a.setRandom();
B b(p,n); b.setRandom();
C c(m,n); c.setOnes();
C rc = c;
std::cout << "Matrix sizes = " << m << "x" << p << " * " << p << "x" << n << "\n";
std::ptrdiff_t mc(m), nc(n), kc(p);
internal::computeProductBlockingSizes<Scalar,Scalar>(kc, mc, nc);
std::cout << "blocking size (mc x kc) = " << mc << " x " << kc << " x " << nc << "\n";
C r = c;
// check the parallel product is correct
#if defined EIGEN_HAS_OPENMP
Eigen::initParallel();
int procs = omp_get_max_threads();
if(procs>1)
{
#ifdef HAVE_BLAS
blas_gemm(a,b,r);
#else
omp_set_num_threads(1);
r.noalias() += a * b;
omp_set_num_threads(procs);
#endif
c.noalias() += a * b;
if(!r.isApprox(c)) std::cerr << "Warning, your parallel product is crap!\n\n";
}
#elif defined HAVE_BLAS
blas_gemm(a,b,r);
c.noalias() += a * b;
if(!r.isApprox(c)) {
std::cout << (r - c).norm()/r.norm() << "\n";
std::cerr << "Warning, your product is crap!\n\n";
}
#else
if(1.*m*n*p<2000.*2000*2000)
{
gemm(a,b,c);
r.noalias() += a.cast<Scalar>() .lazyProduct( b.cast<Scalar>() );
if(!r.isApprox(c)) {
std::cout << (r - c).norm()/r.norm() << "\n";
std::cerr << "Warning, your product is crap!\n\n";
}
}
#endif
#ifdef HAVE_BLAS
BenchTimer tblas;
c = rc;
BENCH(tblas, tries, rep, blas_gemm(a,b,c));
std::cout << "blas cpu " << tblas.best(CPU_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/tblas.best(CPU_TIMER))*1e-9 << " GFLOPS \t(" << tblas.total(CPU_TIMER) << "s)\n";
std::cout << "blas real " << tblas.best(REAL_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/tblas.best(REAL_TIMER))*1e-9 << " GFLOPS \t(" << tblas.total(REAL_TIMER) << "s)\n";
#endif
// warm start
if(b.norm()+a.norm()==123.554) std::cout << "\n";
BenchTimer tmt;
c = rc;
BENCH(tmt, tries, rep, gemm(a,b,c));
std::cout << "eigen cpu " << tmt.best(CPU_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/tmt.best(CPU_TIMER))*1e-9 << " GFLOPS \t(" << tmt.total(CPU_TIMER) << "s)\n";
std::cout << "eigen real " << tmt.best(REAL_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/tmt.best(REAL_TIMER))*1e-9 << " GFLOPS \t(" << tmt.total(REAL_TIMER) << "s)\n";
#ifdef EIGEN_HAS_OPENMP
if(procs>1)
{
BenchTimer tmono;
omp_set_num_threads(1);
Eigen::setNbThreads(1);
c = rc;
BENCH(tmono, tries, rep, gemm(a,b,c));
std::cout << "eigen mono cpu " << tmono.best(CPU_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/tmono.best(CPU_TIMER))*1e-9 << " GFLOPS \t(" << tmono.total(CPU_TIMER) << "s)\n";
std::cout << "eigen mono real " << tmono.best(REAL_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/tmono.best(REAL_TIMER))*1e-9 << " GFLOPS \t(" << tmono.total(REAL_TIMER) << "s)\n";
std::cout << "mt speed up x" << tmono.best(CPU_TIMER) / tmt.best(REAL_TIMER) << " => " << (100.0*tmono.best(CPU_TIMER) / tmt.best(REAL_TIMER))/procs << "%\n";
}
#endif
if(1.*m*n*p<30*30*30)
{
BenchTimer tmt;
c = rc;
BENCH(tmt, tries, rep, c.noalias()+=a.lazyProduct(b));
std::cout << "lazy cpu " << tmt.best(CPU_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/tmt.best(CPU_TIMER))*1e-9 << " GFLOPS \t(" << tmt.total(CPU_TIMER) << "s)\n";
std::cout << "lazy real " << tmt.best(REAL_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/tmt.best(REAL_TIMER))*1e-9 << " GFLOPS \t(" << tmt.total(REAL_TIMER) << "s)\n";
}
#ifdef DECOUPLED
if((NumTraits<A::Scalar>::IsComplex) && (NumTraits<B::Scalar>::IsComplex))
{
M ar(m,p); ar.setRandom();
M ai(m,p); ai.setRandom();
M br(p,n); br.setRandom();
M bi(p,n); bi.setRandom();
M cr(m,n); cr.setRandom();
M ci(m,n); ci.setRandom();
BenchTimer t;
BENCH(t, tries, rep, matlab_cplx_cplx(ar,ai,br,bi,cr,ci));
std::cout << "\"matlab\" cpu " << t.best(CPU_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/t.best(CPU_TIMER))*1e-9 << " GFLOPS \t(" << t.total(CPU_TIMER) << "s)\n";
std::cout << "\"matlab\" real " << t.best(REAL_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/t.best(REAL_TIMER))*1e-9 << " GFLOPS \t(" << t.total(REAL_TIMER) << "s)\n";
}
if((!NumTraits<A::Scalar>::IsComplex) && (NumTraits<B::Scalar>::IsComplex))
{
M a(m,p); a.setRandom();
M br(p,n); br.setRandom();
M bi(p,n); bi.setRandom();
M cr(m,n); cr.setRandom();
M ci(m,n); ci.setRandom();
BenchTimer t;
BENCH(t, tries, rep, matlab_real_cplx(a,br,bi,cr,ci));
std::cout << "\"matlab\" cpu " << t.best(CPU_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/t.best(CPU_TIMER))*1e-9 << " GFLOPS \t(" << t.total(CPU_TIMER) << "s)\n";
std::cout << "\"matlab\" real " << t.best(REAL_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/t.best(REAL_TIMER))*1e-9 << " GFLOPS \t(" << t.total(REAL_TIMER) << "s)\n";
}
if((NumTraits<A::Scalar>::IsComplex) && (!NumTraits<B::Scalar>::IsComplex))
{
M ar(m,p); ar.setRandom();
M ai(m,p); ai.setRandom();
M b(p,n); b.setRandom();
M cr(m,n); cr.setRandom();
M ci(m,n); ci.setRandom();
BenchTimer t;
BENCH(t, tries, rep, matlab_cplx_real(ar,ai,b,cr,ci));
std::cout << "\"matlab\" cpu " << t.best(CPU_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/t.best(CPU_TIMER))*1e-9 << " GFLOPS \t(" << t.total(CPU_TIMER) << "s)\n";
std::cout << "\"matlab\" real " << t.best(REAL_TIMER)/rep << "s \t" << (double(m)*n*p*rep*2/t.best(REAL_TIMER))*1e-9 << " GFLOPS \t(" << t.total(REAL_TIMER) << "s)\n";
}
#endif
return 0;
}
@@ -0,0 +1,57 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2020 Sebastien Boisvert <seb@boisvert.info>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "BenchTimer.h"
#include "../test/MovableScalar.h"
#include <Eigen/Core>
#include <iostream>
#include <utility>
template <typename MatrixType>
void copy_matrix(MatrixType& m)
{
MatrixType tmp(m);
m = tmp;
}
template <typename MatrixType>
void move_matrix(MatrixType&& m)
{
MatrixType tmp(std::move(m));
m = std::move(tmp);
}
template<typename Scalar>
void bench(const std::string& label)
{
using MatrixType = Eigen::Matrix<Eigen::MovableScalar<Scalar>,1,10>;
Eigen::BenchTimer t;
int tries = 10;
int rep = 1000000;
MatrixType data = MatrixType::Random().eval();
MatrixType dest;
BENCH(t, tries, rep, copy_matrix(data));
std::cout << label << " copy semantics: " << 1e3*t.best(Eigen::CPU_TIMER) << " ms" << std::endl;
BENCH(t, tries, rep, move_matrix(std::move(data)));
std::cout << label << " move semantics: " << 1e3*t.best(Eigen::CPU_TIMER) << " ms" << std::endl;
}
int main()
{
bench<float>("float");
bench<double>("double");
return 0;
}
@@ -0,0 +1,28 @@
#!/bin/bash
if (($# < 2)); then
echo "Usage: $0 compilerlist.txt benchfile.cpp"
else
compilerlist=$1
benchfile=$2
g=0
source $compilerlist
# for each compiler, compile benchfile and run the benchmark
for (( i=0 ; i<g ; ++i )) ; do
# check the compiler exists
compiler=`echo ${CLIST[$i]} | cut -d " " -f 1`
if [ -e `which $compiler` ]; then
echo "${CLIST[$i]}"
# echo "${CLIST[$i]} $benchfile -I.. -o bench~"
# if [ -e ./.bench ] ; then rm .bench; fi
${CLIST[$i]} $benchfile -I.. -o .bench && ./.bench 2> /dev/null
echo ""
else
echo "compiler not found: $compiler"
fi
done
fi
@@ -0,0 +1,360 @@
#include <typeinfo>
#include <iostream>
#include <Eigen/Core>
#include "BenchTimer.h"
using namespace Eigen;
using namespace std;
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar sqsumNorm(T& v)
{
return v.norm();
}
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar stableNorm(T& v)
{
return v.stableNorm();
}
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar hypotNorm(T& v)
{
return v.hypotNorm();
}
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar blueNorm(T& v)
{
return v.blueNorm();
}
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar lapackNorm(T& v)
{
typedef typename T::Scalar Scalar;
int n = v.size();
Scalar scale = 0;
Scalar ssq = 1;
for (int i=0;i<n;++i)
{
Scalar ax = std::abs(v.coeff(i));
if (scale >= ax)
{
ssq += numext::abs2(ax/scale);
}
else
{
ssq = Scalar(1) + ssq * numext::abs2(scale/ax);
scale = ax;
}
}
return scale * std::sqrt(ssq);
}
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar twopassNorm(T& v)
{
typedef typename T::Scalar Scalar;
Scalar s = v.array().abs().maxCoeff();
return s*(v/s).norm();
}
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar bl2passNorm(T& v)
{
return v.stableNorm();
}
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar divacNorm(T& v)
{
int n =v.size() / 2;
for (int i=0;i<n;++i)
v(i) = v(2*i)*v(2*i) + v(2*i+1)*v(2*i+1);
n = n/2;
while (n>0)
{
for (int i=0;i<n;++i)
v(i) = v(2*i) + v(2*i+1);
n = n/2;
}
return std::sqrt(v(0));
}
namespace Eigen {
namespace internal {
#ifdef EIGEN_VECTORIZE
Packet4f plt(const Packet4f& a, Packet4f& b) { return _mm_cmplt_ps(a,b); }
Packet2d plt(const Packet2d& a, Packet2d& b) { return _mm_cmplt_pd(a,b); }
Packet4f pandnot(const Packet4f& a, Packet4f& b) { return _mm_andnot_ps(a,b); }
Packet2d pandnot(const Packet2d& a, Packet2d& b) { return _mm_andnot_pd(a,b); }
#endif
}
}
template<typename T>
EIGEN_DONT_INLINE typename T::Scalar pblueNorm(const T& v)
{
#ifndef EIGEN_VECTORIZE
return v.blueNorm();
#else
typedef typename T::Scalar Scalar;
static int nmax = 0;
static Scalar b1, b2, s1m, s2m, overfl, rbig, relerr;
int n;
if(nmax <= 0)
{
int nbig, ibeta, it, iemin, iemax, iexp;
Scalar abig, eps;
nbig = NumTraits<int>::highest(); // largest integer
ibeta = std::numeric_limits<Scalar>::radix; // NumTraits<Scalar>::Base; // base for floating-point numbers
it = NumTraits<Scalar>::digits(); // NumTraits<Scalar>::Mantissa; // number of base-beta digits in mantissa
iemin = NumTraits<Scalar>::min_exponent(); // minimum exponent
iemax = NumTraits<Scalar>::max_exponent(); // maximum exponent
rbig = NumTraits<Scalar>::highest(); // largest floating-point number
// Check the basic machine-dependent constants.
if(iemin > 1 - 2*it || 1+it>iemax || (it==2 && ibeta<5)
|| (it<=4 && ibeta <= 3 ) || it<2)
{
eigen_assert(false && "the algorithm cannot be guaranteed on this computer");
}
iexp = -((1-iemin)/2);
b1 = std::pow(ibeta, iexp); // lower boundary of midrange
iexp = (iemax + 1 - it)/2;
b2 = std::pow(ibeta,iexp); // upper boundary of midrange
iexp = (2-iemin)/2;
s1m = std::pow(ibeta,iexp); // scaling factor for lower range
iexp = - ((iemax+it)/2);
s2m = std::pow(ibeta,iexp); // scaling factor for upper range
overfl = rbig*s2m; // overflow boundary for abig
eps = std::pow(ibeta, 1-it);
relerr = std::sqrt(eps); // tolerance for neglecting asml
abig = 1.0/eps - 1.0;
if (Scalar(nbig)>abig) nmax = abig; // largest safe n
else nmax = nbig;
}
typedef typename internal::packet_traits<Scalar>::type Packet;
const int ps = internal::packet_traits<Scalar>::size;
Packet pasml = internal::pset1<Packet>(Scalar(0));
Packet pamed = internal::pset1<Packet>(Scalar(0));
Packet pabig = internal::pset1<Packet>(Scalar(0));
Packet ps2m = internal::pset1<Packet>(s2m);
Packet ps1m = internal::pset1<Packet>(s1m);
Packet pb2 = internal::pset1<Packet>(b2);
Packet pb1 = internal::pset1<Packet>(b1);
for(int j=0; j<v.size(); j+=ps)
{
Packet ax = internal::pabs(v.template packet<Aligned>(j));
Packet ax_s2m = internal::pmul(ax,ps2m);
Packet ax_s1m = internal::pmul(ax,ps1m);
Packet maskBig = internal::plt(pb2,ax);
Packet maskSml = internal::plt(ax,pb1);
// Packet maskMed = internal::pand(maskSml,maskBig);
// Packet scale = internal::pset1(Scalar(0));
// scale = internal::por(scale, internal::pand(maskBig,ps2m));
// scale = internal::por(scale, internal::pand(maskSml,ps1m));
// scale = internal::por(scale, internal::pandnot(internal::pset1(Scalar(1)),maskMed));
// ax = internal::pmul(ax,scale);
// ax = internal::pmul(ax,ax);
// pabig = internal::padd(pabig, internal::pand(maskBig, ax));
// pasml = internal::padd(pasml, internal::pand(maskSml, ax));
// pamed = internal::padd(pamed, internal::pandnot(ax,maskMed));
pabig = internal::padd(pabig, internal::pand(maskBig, internal::pmul(ax_s2m,ax_s2m)));
pasml = internal::padd(pasml, internal::pand(maskSml, internal::pmul(ax_s1m,ax_s1m)));
pamed = internal::padd(pamed, internal::pandnot(internal::pmul(ax,ax),internal::pand(maskSml,maskBig)));
}
Scalar abig = internal::predux(pabig);
Scalar asml = internal::predux(pasml);
Scalar amed = internal::predux(pamed);
if(abig > Scalar(0))
{
abig = std::sqrt(abig);
if(abig > overfl)
{
eigen_assert(false && "overflow");
return rbig;
}
if(amed > Scalar(0))
{
abig = abig/s2m;
amed = std::sqrt(amed);
}
else
{
return abig/s2m;
}
}
else if(asml > Scalar(0))
{
if (amed > Scalar(0))
{
abig = std::sqrt(amed);
amed = std::sqrt(asml) / s1m;
}
else
{
return std::sqrt(asml)/s1m;
}
}
else
{
return std::sqrt(amed);
}
asml = std::min(abig, amed);
abig = std::max(abig, amed);
if(asml <= abig*relerr)
return abig;
else
return abig * std::sqrt(Scalar(1) + numext::abs2(asml/abig));
#endif
}
#define BENCH_PERF(NRM) { \
float af = 0; double ad = 0; std::complex<float> ac = 0; \
Eigen::BenchTimer tf, td, tcf; tf.reset(); td.reset(); tcf.reset();\
for (int k=0; k<tries; ++k) { \
tf.start(); \
for (int i=0; i<iters; ++i) { af += NRM(vf); } \
tf.stop(); \
} \
for (int k=0; k<tries; ++k) { \
td.start(); \
for (int i=0; i<iters; ++i) { ad += NRM(vd); } \
td.stop(); \
} \
/*for (int k=0; k<std::max(1,tries/3); ++k) { \
tcf.start(); \
for (int i=0; i<iters; ++i) { ac += NRM(vcf); } \
tcf.stop(); \
} */\
std::cout << #NRM << "\t" << tf.value() << " " << td.value() << " " << tcf.value() << "\n"; \
}
void check_accuracy(double basef, double based, int s)
{
double yf = basef * std::abs(internal::random<double>());
double yd = based * std::abs(internal::random<double>());
VectorXf vf = VectorXf::Ones(s) * yf;
VectorXd vd = VectorXd::Ones(s) * yd;
std::cout << "reference\t" << std::sqrt(double(s))*yf << "\t" << std::sqrt(double(s))*yd << "\n";
std::cout << "sqsumNorm\t" << sqsumNorm(vf) << "\t" << sqsumNorm(vd) << "\n";
std::cout << "hypotNorm\t" << hypotNorm(vf) << "\t" << hypotNorm(vd) << "\n";
std::cout << "blueNorm\t" << blueNorm(vf) << "\t" << blueNorm(vd) << "\n";
std::cout << "pblueNorm\t" << pblueNorm(vf) << "\t" << pblueNorm(vd) << "\n";
std::cout << "lapackNorm\t" << lapackNorm(vf) << "\t" << lapackNorm(vd) << "\n";
std::cout << "twopassNorm\t" << twopassNorm(vf) << "\t" << twopassNorm(vd) << "\n";
std::cout << "bl2passNorm\t" << bl2passNorm(vf) << "\t" << bl2passNorm(vd) << "\n";
}
void check_accuracy_var(int ef0, int ef1, int ed0, int ed1, int s)
{
VectorXf vf(s);
VectorXd vd(s);
for (int i=0; i<s; ++i)
{
vf[i] = std::abs(internal::random<double>()) * std::pow(double(10), internal::random<int>(ef0,ef1));
vd[i] = std::abs(internal::random<double>()) * std::pow(double(10), internal::random<int>(ed0,ed1));
}
//std::cout << "reference\t" << internal::sqrt(double(s))*yf << "\t" << internal::sqrt(double(s))*yd << "\n";
std::cout << "sqsumNorm\t" << sqsumNorm(vf) << "\t" << sqsumNorm(vd) << "\t" << sqsumNorm(vf.cast<long double>()) << "\t" << sqsumNorm(vd.cast<long double>()) << "\n";
std::cout << "hypotNorm\t" << hypotNorm(vf) << "\t" << hypotNorm(vd) << "\t" << hypotNorm(vf.cast<long double>()) << "\t" << hypotNorm(vd.cast<long double>()) << "\n";
std::cout << "blueNorm\t" << blueNorm(vf) << "\t" << blueNorm(vd) << "\t" << blueNorm(vf.cast<long double>()) << "\t" << blueNorm(vd.cast<long double>()) << "\n";
std::cout << "pblueNorm\t" << pblueNorm(vf) << "\t" << pblueNorm(vd) << "\t" << blueNorm(vf.cast<long double>()) << "\t" << blueNorm(vd.cast<long double>()) << "\n";
std::cout << "lapackNorm\t" << lapackNorm(vf) << "\t" << lapackNorm(vd) << "\t" << lapackNorm(vf.cast<long double>()) << "\t" << lapackNorm(vd.cast<long double>()) << "\n";
std::cout << "twopassNorm\t" << twopassNorm(vf) << "\t" << twopassNorm(vd) << "\t" << twopassNorm(vf.cast<long double>()) << "\t" << twopassNorm(vd.cast<long double>()) << "\n";
// std::cout << "bl2passNorm\t" << bl2passNorm(vf) << "\t" << bl2passNorm(vd) << "\t" << bl2passNorm(vf.cast<long double>()) << "\t" << bl2passNorm(vd.cast<long double>()) << "\n";
}
int main(int argc, char** argv)
{
int tries = 10;
int iters = 100000;
double y = 1.1345743233455785456788e12 * internal::random<double>();
VectorXf v = VectorXf::Ones(1024) * y;
// return 0;
int s = 10000;
double basef_ok = 1.1345743233455785456788e15;
double based_ok = 1.1345743233455785456788e95;
double basef_under = 1.1345743233455785456788e-27;
double based_under = 1.1345743233455785456788e-303;
double basef_over = 1.1345743233455785456788e+27;
double based_over = 1.1345743233455785456788e+302;
std::cout.precision(20);
std::cerr << "\nNo under/overflow:\n";
check_accuracy(basef_ok, based_ok, s);
std::cerr << "\nUnderflow:\n";
check_accuracy(basef_under, based_under, s);
std::cerr << "\nOverflow:\n";
check_accuracy(basef_over, based_over, s);
std::cerr << "\nVarying (over):\n";
for (int k=0; k<1; ++k)
{
check_accuracy_var(20,27,190,302,s);
std::cout << "\n";
}
std::cerr << "\nVarying (under):\n";
for (int k=0; k<1; ++k)
{
check_accuracy_var(-27,20,-302,-190,s);
std::cout << "\n";
}
y = 1;
std::cout.precision(4);
int s1 = 1024*1024*32;
std::cerr << "Performance (out of cache, " << s1 << "):\n";
{
int iters = 1;
VectorXf vf = VectorXf::Random(s1) * y;
VectorXd vd = VectorXd::Random(s1) * y;
VectorXcf vcf = VectorXcf::Random(s1) * y;
BENCH_PERF(sqsumNorm);
BENCH_PERF(stableNorm);
BENCH_PERF(blueNorm);
BENCH_PERF(pblueNorm);
BENCH_PERF(lapackNorm);
BENCH_PERF(hypotNorm);
BENCH_PERF(twopassNorm);
BENCH_PERF(bl2passNorm);
}
std::cerr << "\nPerformance (in cache, " << 512 << "):\n";
{
int iters = 100000;
VectorXf vf = VectorXf::Random(512) * y;
VectorXd vd = VectorXd::Random(512) * y;
VectorXcf vcf = VectorXcf::Random(512) * y;
BENCH_PERF(sqsumNorm);
BENCH_PERF(stableNorm);
BENCH_PERF(blueNorm);
BENCH_PERF(pblueNorm);
BENCH_PERF(lapackNorm);
BENCH_PERF(hypotNorm);
BENCH_PERF(twopassNorm);
BENCH_PERF(bl2passNorm);
}
}
@@ -0,0 +1,84 @@
#include <iostream>
#include <Eigen/Core>
#include <bench/BenchUtil.h>
using namespace Eigen;
#ifndef REPEAT
#define REPEAT 100000
#endif
#ifndef TRIES
#define TRIES 20
#endif
typedef double Scalar;
template <typename MatrixType>
__attribute__ ((noinline)) void bench_reverse(const MatrixType& m)
{
int rows = m.rows();
int cols = m.cols();
int size = m.size();
int repeats = (REPEAT*1000)/size;
MatrixType a = MatrixType::Random(rows,cols);
MatrixType b = MatrixType::Random(rows,cols);
BenchTimer timerB, timerH, timerV;
Scalar acc = 0;
int r = internal::random<int>(0,rows-1);
int c = internal::random<int>(0,cols-1);
for (int t=0; t<TRIES; ++t)
{
timerB.start();
for (int k=0; k<repeats; ++k)
{
asm("#begin foo");
b = a.reverse();
asm("#end foo");
acc += b.coeff(r,c);
}
timerB.stop();
}
if (MatrixType::RowsAtCompileTime==Dynamic)
std::cout << "dyn ";
else
std::cout << "fixed ";
std::cout << rows << " x " << cols << " \t"
<< (timerB.value() * REPEAT) / repeats << "s "
<< "(" << 1e-6 * size*repeats/timerB.value() << " MFLOPS)\t";
std::cout << "\n";
// make sure the compiler does not optimize too much
if (acc==123)
std::cout << acc;
}
int main(int argc, char* argv[])
{
const int dynsizes[] = {4,6,8,16,24,32,49,64,128,256,512,900,0};
std::cout << "size no sqrt standard";
// #ifdef BENCH_GSL
// std::cout << " GSL (standard + double + ATLAS) ";
// #endif
std::cout << "\n";
for (uint i=0; dynsizes[i]>0; ++i)
{
bench_reverse(Matrix<Scalar,Dynamic,Dynamic>(dynsizes[i],dynsizes[i]));
bench_reverse(Matrix<Scalar,Dynamic,1>(dynsizes[i]*dynsizes[i]));
}
// bench_reverse(Matrix<Scalar,2,2>());
// bench_reverse(Matrix<Scalar,3,3>());
// bench_reverse(Matrix<Scalar,4,4>());
// bench_reverse(Matrix<Scalar,5,5>());
// bench_reverse(Matrix<Scalar,6,6>());
// bench_reverse(Matrix<Scalar,7,7>());
// bench_reverse(Matrix<Scalar,8,8>());
// bench_reverse(Matrix<Scalar,12,12>());
// bench_reverse(Matrix<Scalar,16,16>());
return 0;
}
@@ -0,0 +1,18 @@
#include <iostream>
#include <Eigen/Core>
using namespace Eigen;
using namespace std;
int main()
{
typedef Matrix<SCALAR,Eigen::Dynamic,1> Vec;
Vec v(SIZE);
v.setZero();
v[0] = 1;
v[1] = 2;
for(int i = 0; i < 1000000; i++)
{
v.coeffRef(0) += v.sum() * SCALAR(1e-20);
}
cout << v.sum() << endl;
}
@@ -0,0 +1,677 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2015 Benoit Jacob <benoitjacob@google.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <iostream>
#include <cstdint>
#include <cstdlib>
#include <vector>
#include <fstream>
#include <memory>
#include <cstdio>
bool eigen_use_specific_block_size;
int eigen_block_size_k, eigen_block_size_m, eigen_block_size_n;
#define EIGEN_TEST_SPECIFIC_BLOCKING_SIZES eigen_use_specific_block_size
#define EIGEN_TEST_SPECIFIC_BLOCKING_SIZE_K eigen_block_size_k
#define EIGEN_TEST_SPECIFIC_BLOCKING_SIZE_M eigen_block_size_m
#define EIGEN_TEST_SPECIFIC_BLOCKING_SIZE_N eigen_block_size_n
#include <Eigen/Core>
#include <bench/BenchTimer.h>
using namespace Eigen;
using namespace std;
static BenchTimer timer;
// how many times we repeat each measurement.
// measurements are randomly shuffled - we're not doing
// all N identical measurements in a row.
const int measurement_repetitions = 3;
// Timings below this value are too short to be accurate,
// we'll repeat measurements with more iterations until
// we get a timing above that threshold.
const float min_accurate_time = 1e-2f;
// See --min-working-set-size command line parameter.
size_t min_working_set_size = 0;
float max_clock_speed = 0.0f;
// range of sizes that we will benchmark (in all 3 K,M,N dimensions)
const size_t maxsize = 2048;
const size_t minsize = 16;
typedef MatrixXf MatrixType;
typedef MatrixType::Scalar Scalar;
typedef internal::packet_traits<Scalar>::type Packet;
static_assert((maxsize & (maxsize - 1)) == 0, "maxsize must be a power of two");
static_assert((minsize & (minsize - 1)) == 0, "minsize must be a power of two");
static_assert(maxsize > minsize, "maxsize must be larger than minsize");
static_assert(maxsize < (minsize << 16), "maxsize must be less than (minsize<<16)");
// just a helper to store a triple of K,M,N sizes for matrix product
struct size_triple_t
{
size_t k, m, n;
size_triple_t() : k(0), m(0), n(0) {}
size_triple_t(size_t _k, size_t _m, size_t _n) : k(_k), m(_m), n(_n) {}
size_triple_t(const size_triple_t& o) : k(o.k), m(o.m), n(o.n) {}
size_triple_t(uint16_t compact)
{
k = 1 << ((compact & 0xf00) >> 8);
m = 1 << ((compact & 0x0f0) >> 4);
n = 1 << ((compact & 0x00f) >> 0);
}
};
uint8_t log2_pot(size_t x) {
size_t l = 0;
while (x >>= 1) l++;
return l;
}
// Convert between size tripes and a compact form fitting in 12 bits
// where each size, which must be a POT, is encoded as its log2, on 4 bits
// so the largest representable size is 2^15 == 32k ... big enough.
uint16_t compact_size_triple(size_t k, size_t m, size_t n)
{
return (log2_pot(k) << 8) | (log2_pot(m) << 4) | log2_pot(n);
}
uint16_t compact_size_triple(const size_triple_t& t)
{
return compact_size_triple(t.k, t.m, t.n);
}
// A single benchmark. Initially only contains benchmark params.
// Then call run(), which stores the result in the gflops field.
struct benchmark_t
{
uint16_t compact_product_size;
uint16_t compact_block_size;
bool use_default_block_size;
float gflops;
benchmark_t()
: compact_product_size(0)
, compact_block_size(0)
, use_default_block_size(false)
, gflops(0)
{
}
benchmark_t(size_t pk, size_t pm, size_t pn,
size_t bk, size_t bm, size_t bn)
: compact_product_size(compact_size_triple(pk, pm, pn))
, compact_block_size(compact_size_triple(bk, bm, bn))
, use_default_block_size(false)
, gflops(0)
{}
benchmark_t(size_t pk, size_t pm, size_t pn)
: compact_product_size(compact_size_triple(pk, pm, pn))
, compact_block_size(0)
, use_default_block_size(true)
, gflops(0)
{}
void run();
};
ostream& operator<<(ostream& s, const benchmark_t& b)
{
s << hex << b.compact_product_size << dec;
if (b.use_default_block_size) {
size_triple_t t(b.compact_product_size);
Index k = t.k, m = t.m, n = t.n;
internal::computeProductBlockingSizes<Scalar, Scalar>(k, m, n);
s << " default(" << k << ", " << m << ", " << n << ")";
} else {
s << " " << hex << b.compact_block_size << dec;
}
s << " " << b.gflops;
return s;
}
// We sort first by increasing benchmark parameters,
// then by decreasing performance.
bool operator<(const benchmark_t& b1, const benchmark_t& b2)
{
return b1.compact_product_size < b2.compact_product_size ||
(b1.compact_product_size == b2.compact_product_size && (
(b1.compact_block_size < b2.compact_block_size || (
b1.compact_block_size == b2.compact_block_size &&
b1.gflops > b2.gflops))));
}
void benchmark_t::run()
{
size_triple_t productsizes(compact_product_size);
if (use_default_block_size) {
eigen_use_specific_block_size = false;
} else {
// feed eigen with our custom blocking params
eigen_use_specific_block_size = true;
size_triple_t blocksizes(compact_block_size);
eigen_block_size_k = blocksizes.k;
eigen_block_size_m = blocksizes.m;
eigen_block_size_n = blocksizes.n;
}
// set up the matrix pool
const size_t combined_three_matrices_sizes =
sizeof(Scalar) *
(productsizes.k * productsizes.m +
productsizes.k * productsizes.n +
productsizes.m * productsizes.n);
// 64 M is large enough that nobody has a cache bigger than that,
// while still being small enough that everybody has this much RAM,
// so conveniently we don't need to special-case platforms here.
const size_t unlikely_large_cache_size = 64 << 20;
const size_t working_set_size =
min_working_set_size ? min_working_set_size : unlikely_large_cache_size;
const size_t matrix_pool_size =
1 + working_set_size / combined_three_matrices_sizes;
MatrixType *lhs = new MatrixType[matrix_pool_size];
MatrixType *rhs = new MatrixType[matrix_pool_size];
MatrixType *dst = new MatrixType[matrix_pool_size];
for (size_t i = 0; i < matrix_pool_size; i++) {
lhs[i] = MatrixType::Zero(productsizes.m, productsizes.k);
rhs[i] = MatrixType::Zero(productsizes.k, productsizes.n);
dst[i] = MatrixType::Zero(productsizes.m, productsizes.n);
}
// main benchmark loop
int iters_at_a_time = 1;
float time_per_iter = 0.0f;
size_t matrix_index = 0;
while (true) {
double starttime = timer.getCpuTime();
for (int i = 0; i < iters_at_a_time; i++) {
dst[matrix_index].noalias() = lhs[matrix_index] * rhs[matrix_index];
matrix_index++;
if (matrix_index == matrix_pool_size) {
matrix_index = 0;
}
}
double endtime = timer.getCpuTime();
const float timing = float(endtime - starttime);
if (timing >= min_accurate_time) {
time_per_iter = timing / iters_at_a_time;
break;
}
iters_at_a_time *= 2;
}
delete[] lhs;
delete[] rhs;
delete[] dst;
gflops = 2e-9 * productsizes.k * productsizes.m * productsizes.n / time_per_iter;
}
void print_cpuinfo()
{
#ifdef __linux__
cout << "contents of /proc/cpuinfo:" << endl;
string line;
ifstream cpuinfo("/proc/cpuinfo");
if (cpuinfo.is_open()) {
while (getline(cpuinfo, line)) {
cout << line << endl;
}
cpuinfo.close();
}
cout << endl;
#elif defined __APPLE__
cout << "output of sysctl hw:" << endl;
system("sysctl hw");
cout << endl;
#endif
}
template <typename T>
string type_name()
{
return "unknown";
}
template<>
string type_name<float>()
{
return "float";
}
template<>
string type_name<double>()
{
return "double";
}
struct action_t
{
virtual const char* invokation_name() const { abort(); return nullptr; }
virtual void run() const { abort(); }
virtual ~action_t() {}
};
void show_usage_and_exit(int /*argc*/, char* argv[],
const vector<unique_ptr<action_t>>& available_actions)
{
cerr << "usage: " << argv[0] << " <action> [options...]" << endl << endl;
cerr << "available actions:" << endl << endl;
for (auto it = available_actions.begin(); it != available_actions.end(); ++it) {
cerr << " " << (*it)->invokation_name() << endl;
}
cerr << endl;
cerr << "options:" << endl << endl;
cerr << " --min-working-set-size=N:" << endl;
cerr << " Set the minimum working set size to N bytes." << endl;
cerr << " This is rounded up as needed to a multiple of matrix size." << endl;
cerr << " A larger working set lowers the chance of a warm cache." << endl;
cerr << " The default value 0 means use a large enough working" << endl;
cerr << " set to likely outsize caches." << endl;
cerr << " A value of 1 (that is, 1 byte) would mean don't do anything to" << endl;
cerr << " avoid warm caches." << endl;
exit(1);
}
float measure_clock_speed()
{
cerr << "Measuring clock speed... \r" << flush;
vector<float> all_gflops;
for (int i = 0; i < 8; i++) {
benchmark_t b(1024, 1024, 1024);
b.run();
all_gflops.push_back(b.gflops);
}
sort(all_gflops.begin(), all_gflops.end());
float stable_estimate = all_gflops[2] + all_gflops[3] + all_gflops[4] + all_gflops[5];
// multiply by an arbitrary constant to discourage trying doing anything with the
// returned values besides just comparing them with each other.
float result = stable_estimate * 123.456f;
return result;
}
struct human_duration_t
{
int seconds;
human_duration_t(int s) : seconds(s) {}
};
ostream& operator<<(ostream& s, const human_duration_t& d)
{
int remainder = d.seconds;
if (remainder > 3600) {
int hours = remainder / 3600;
s << hours << " h ";
remainder -= hours * 3600;
}
if (remainder > 60) {
int minutes = remainder / 60;
s << minutes << " min ";
remainder -= minutes * 60;
}
if (d.seconds < 600) {
s << remainder << " s";
}
return s;
}
const char session_filename[] = "/data/local/tmp/benchmark-blocking-sizes-session.data";
void serialize_benchmarks(const char* filename, const vector<benchmark_t>& benchmarks, size_t first_benchmark_to_run)
{
FILE* file = fopen(filename, "w");
if (!file) {
cerr << "Could not open file " << filename << " for writing." << endl;
cerr << "Do you have write permissions on the current working directory?" << endl;
exit(1);
}
size_t benchmarks_vector_size = benchmarks.size();
fwrite(&max_clock_speed, sizeof(max_clock_speed), 1, file);
fwrite(&benchmarks_vector_size, sizeof(benchmarks_vector_size), 1, file);
fwrite(&first_benchmark_to_run, sizeof(first_benchmark_to_run), 1, file);
fwrite(benchmarks.data(), sizeof(benchmark_t), benchmarks.size(), file);
fclose(file);
}
bool deserialize_benchmarks(const char* filename, vector<benchmark_t>& benchmarks, size_t& first_benchmark_to_run)
{
FILE* file = fopen(filename, "r");
if (!file) {
return false;
}
if (1 != fread(&max_clock_speed, sizeof(max_clock_speed), 1, file)) {
return false;
}
size_t benchmarks_vector_size = 0;
if (1 != fread(&benchmarks_vector_size, sizeof(benchmarks_vector_size), 1, file)) {
return false;
}
if (1 != fread(&first_benchmark_to_run, sizeof(first_benchmark_to_run), 1, file)) {
return false;
}
benchmarks.resize(benchmarks_vector_size);
if (benchmarks.size() != fread(benchmarks.data(), sizeof(benchmark_t), benchmarks.size(), file)) {
return false;
}
unlink(filename);
return true;
}
void try_run_some_benchmarks(
vector<benchmark_t>& benchmarks,
double time_start,
size_t& first_benchmark_to_run)
{
if (first_benchmark_to_run == benchmarks.size()) {
return;
}
double time_last_progress_update = 0;
double time_last_clock_speed_measurement = 0;
double time_now = 0;
size_t benchmark_index = first_benchmark_to_run;
while (true) {
float ratio_done = float(benchmark_index) / benchmarks.size();
time_now = timer.getRealTime();
// We check clock speed every minute and at the end.
if (benchmark_index == benchmarks.size() ||
time_now > time_last_clock_speed_measurement + 60.0f)
{
time_last_clock_speed_measurement = time_now;
// Ensure that clock speed is as expected
float current_clock_speed = measure_clock_speed();
// The tolerance needs to be smaller than the relative difference between
// clock speeds that a device could operate under.
// It seems unlikely that a device would be throttling clock speeds by
// amounts smaller than 2%.
// With a value of 1%, I was getting within noise on a Sandy Bridge.
const float clock_speed_tolerance = 0.02f;
if (current_clock_speed > (1 + clock_speed_tolerance) * max_clock_speed) {
// Clock speed is now higher than we previously measured.
// Either our initial measurement was inaccurate, which won't happen
// too many times as we are keeping the best clock speed value and
// and allowing some tolerance; or something really weird happened,
// which invalidates all benchmark results collected so far.
// Either way, we better restart all over again now.
if (benchmark_index) {
cerr << "Restarting at " << 100.0f * ratio_done
<< " % because clock speed increased. " << endl;
}
max_clock_speed = current_clock_speed;
first_benchmark_to_run = 0;
return;
}
bool rerun_last_tests = false;
if (current_clock_speed < (1 - clock_speed_tolerance) * max_clock_speed) {
cerr << "Measurements completed so far: "
<< 100.0f * ratio_done
<< " % " << endl;
cerr << "Clock speed seems to be only "
<< current_clock_speed/max_clock_speed
<< " times what it used to be." << endl;
unsigned int seconds_to_sleep_if_lower_clock_speed = 1;
while (current_clock_speed < (1 - clock_speed_tolerance) * max_clock_speed) {
if (seconds_to_sleep_if_lower_clock_speed > 32) {
cerr << "Sleeping longer probably won't make a difference." << endl;
cerr << "Serializing benchmarks to " << session_filename << endl;
serialize_benchmarks(session_filename, benchmarks, first_benchmark_to_run);
cerr << "Now restart this benchmark, and it should pick up where we left." << endl;
exit(2);
}
rerun_last_tests = true;
cerr << "Sleeping "
<< seconds_to_sleep_if_lower_clock_speed
<< " s... \r" << endl;
sleep(seconds_to_sleep_if_lower_clock_speed);
current_clock_speed = measure_clock_speed();
seconds_to_sleep_if_lower_clock_speed *= 2;
}
}
if (rerun_last_tests) {
cerr << "Redoing the last "
<< 100.0f * float(benchmark_index - first_benchmark_to_run) / benchmarks.size()
<< " % because clock speed had been low. " << endl;
return;
}
// nothing wrong with the clock speed so far, so there won't be a need to rerun
// benchmarks run so far in case we later encounter a lower clock speed.
first_benchmark_to_run = benchmark_index;
}
if (benchmark_index == benchmarks.size()) {
// We're done!
first_benchmark_to_run = benchmarks.size();
// Erase progress info
cerr << " " << endl;
return;
}
// Display progress info on stderr
if (time_now > time_last_progress_update + 1.0f) {
time_last_progress_update = time_now;
cerr << "Measurements... " << 100.0f * ratio_done
<< " %, ETA "
<< human_duration_t(float(time_now - time_start) * (1.0f - ratio_done) / ratio_done)
<< " \r" << flush;
}
// This is where we actually run a benchmark!
benchmarks[benchmark_index].run();
benchmark_index++;
}
}
void run_benchmarks(vector<benchmark_t>& benchmarks)
{
size_t first_benchmark_to_run;
vector<benchmark_t> deserialized_benchmarks;
bool use_deserialized_benchmarks = false;
if (deserialize_benchmarks(session_filename, deserialized_benchmarks, first_benchmark_to_run)) {
cerr << "Found serialized session with "
<< 100.0f * first_benchmark_to_run / deserialized_benchmarks.size()
<< " % already done" << endl;
if (deserialized_benchmarks.size() == benchmarks.size() &&
first_benchmark_to_run > 0 &&
first_benchmark_to_run < benchmarks.size())
{
use_deserialized_benchmarks = true;
}
}
if (use_deserialized_benchmarks) {
benchmarks = deserialized_benchmarks;
} else {
// not using deserialized benchmarks, starting from scratch
first_benchmark_to_run = 0;
// Randomly shuffling benchmarks allows us to get accurate enough progress info,
// as now the cheap/expensive benchmarks are randomly mixed so they average out.
// It also means that if data is corrupted for some time span, the odds are that
// not all repetitions of a given benchmark will be corrupted.
random_shuffle(benchmarks.begin(), benchmarks.end());
}
for (int i = 0; i < 4; i++) {
max_clock_speed = max(max_clock_speed, measure_clock_speed());
}
double time_start = 0.0;
while (first_benchmark_to_run < benchmarks.size()) {
if (first_benchmark_to_run == 0) {
time_start = timer.getRealTime();
}
try_run_some_benchmarks(benchmarks,
time_start,
first_benchmark_to_run);
}
// Sort timings by increasing benchmark parameters, and decreasing gflops.
// The latter is very important. It means that we can ignore all but the first
// benchmark with given parameters.
sort(benchmarks.begin(), benchmarks.end());
// Collect best (i.e. now first) results for each parameter values.
vector<benchmark_t> best_benchmarks;
for (auto it = benchmarks.begin(); it != benchmarks.end(); ++it) {
if (best_benchmarks.empty() ||
best_benchmarks.back().compact_product_size != it->compact_product_size ||
best_benchmarks.back().compact_block_size != it->compact_block_size)
{
best_benchmarks.push_back(*it);
}
}
// keep and return only the best benchmarks
benchmarks = best_benchmarks;
}
struct measure_all_pot_sizes_action_t : action_t
{
virtual const char* invokation_name() const { return "all-pot-sizes"; }
virtual void run() const
{
vector<benchmark_t> benchmarks;
for (int repetition = 0; repetition < measurement_repetitions; repetition++) {
for (size_t ksize = minsize; ksize <= maxsize; ksize *= 2) {
for (size_t msize = minsize; msize <= maxsize; msize *= 2) {
for (size_t nsize = minsize; nsize <= maxsize; nsize *= 2) {
for (size_t kblock = minsize; kblock <= ksize; kblock *= 2) {
for (size_t mblock = minsize; mblock <= msize; mblock *= 2) {
for (size_t nblock = minsize; nblock <= nsize; nblock *= 2) {
benchmarks.emplace_back(ksize, msize, nsize, kblock, mblock, nblock);
}
}
}
}
}
}
}
run_benchmarks(benchmarks);
cout << "BEGIN MEASUREMENTS ALL POT SIZES" << endl;
for (auto it = benchmarks.begin(); it != benchmarks.end(); ++it) {
cout << *it << endl;
}
}
};
struct measure_default_sizes_action_t : action_t
{
virtual const char* invokation_name() const { return "default-sizes"; }
virtual void run() const
{
vector<benchmark_t> benchmarks;
for (int repetition = 0; repetition < measurement_repetitions; repetition++) {
for (size_t ksize = minsize; ksize <= maxsize; ksize *= 2) {
for (size_t msize = minsize; msize <= maxsize; msize *= 2) {
for (size_t nsize = minsize; nsize <= maxsize; nsize *= 2) {
benchmarks.emplace_back(ksize, msize, nsize);
}
}
}
}
run_benchmarks(benchmarks);
cout << "BEGIN MEASUREMENTS DEFAULT SIZES" << endl;
for (auto it = benchmarks.begin(); it != benchmarks.end(); ++it) {
cout << *it << endl;
}
}
};
int main(int argc, char* argv[])
{
double time_start = timer.getRealTime();
cout.precision(4);
cerr.precision(4);
vector<unique_ptr<action_t>> available_actions;
available_actions.emplace_back(new measure_all_pot_sizes_action_t);
available_actions.emplace_back(new measure_default_sizes_action_t);
auto action = available_actions.end();
if (argc <= 1) {
show_usage_and_exit(argc, argv, available_actions);
}
for (auto it = available_actions.begin(); it != available_actions.end(); ++it) {
if (!strcmp(argv[1], (*it)->invokation_name())) {
action = it;
break;
}
}
if (action == available_actions.end()) {
show_usage_and_exit(argc, argv, available_actions);
}
for (int i = 2; i < argc; i++) {
if (argv[i] == strstr(argv[i], "--min-working-set-size=")) {
const char* equals_sign = strchr(argv[i], '=');
min_working_set_size = strtoul(equals_sign+1, nullptr, 10);
} else {
cerr << "unrecognized option: " << argv[i] << endl << endl;
show_usage_and_exit(argc, argv, available_actions);
}
}
print_cpuinfo();
cout << "benchmark parameters:" << endl;
cout << "pointer size: " << 8*sizeof(void*) << " bits" << endl;
cout << "scalar type: " << type_name<Scalar>() << endl;
cout << "packet size: " << internal::packet_traits<MatrixType::Scalar>::size << endl;
cout << "minsize = " << minsize << endl;
cout << "maxsize = " << maxsize << endl;
cout << "measurement_repetitions = " << measurement_repetitions << endl;
cout << "min_accurate_time = " << min_accurate_time << endl;
cout << "min_working_set_size = " << min_working_set_size;
if (min_working_set_size == 0) {
cout << " (try to outsize caches)";
}
cout << endl << endl;
(*action)->run();
double time_end = timer.getRealTime();
cerr << "Finished in " << human_duration_t(time_end - time_start) << endl;
}
@@ -0,0 +1,39 @@
// g++ -O3 -DNDEBUG -DMATSIZE=<x> benchmark.cpp -o benchmark && time ./benchmark
#include <iostream>
#include <Eigen/Core>
#ifndef MATSIZE
#define MATSIZE 3
#endif
using namespace std;
using namespace Eigen;
#ifndef REPEAT
#define REPEAT 40000000
#endif
#ifndef SCALAR
#define SCALAR double
#endif
int main(int argc, char *argv[])
{
Matrix<SCALAR,MATSIZE,MATSIZE> I = Matrix<SCALAR,MATSIZE,MATSIZE>::Ones();
Matrix<SCALAR,MATSIZE,MATSIZE> m;
for(int i = 0; i < MATSIZE; i++)
for(int j = 0; j < MATSIZE; j++)
{
m(i,j) = (i+MATSIZE*j);
}
asm("#begin");
for(int a = 0; a < REPEAT; a++)
{
m = Matrix<SCALAR,MATSIZE,MATSIZE>::Ones() + 0.00005 * (m + (m*m));
}
asm("#end");
cout << m << endl;
return 0;
}
@@ -0,0 +1,38 @@
// g++ -O3 -DNDEBUG benchmarkX.cpp -o benchmarkX && time ./benchmarkX
#include <iostream>
#include <Eigen/Core>
using namespace std;
using namespace Eigen;
#ifndef REPEAT
#define REPEAT 10000
#endif
#ifndef SCALAR
#define SCALAR float
#endif
int main(int argc, char *argv[])
{
typedef Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> Mat;
Mat m(100, 100);
m.setRandom();
for(int a = 0; a < REPEAT; a++)
{
int r, c, nr, nc;
r = Eigen::internal::random<int>(0,10);
c = Eigen::internal::random<int>(0,10);
nr = Eigen::internal::random<int>(50,80);
nc = Eigen::internal::random<int>(50,80);
m.block(r,c,nr,nc) += Mat::Ones(nr,nc);
m.block(r,c,nr,nc) *= SCALAR(10);
m.block(r,c,nr,nc) -= Mat::constant(nr,nc,10);
m.block(r,c,nr,nc) /= SCALAR(10);
}
cout << m[0] << endl;
return 0;
}
@@ -0,0 +1,36 @@
// g++ -fopenmp -I .. -O3 -DNDEBUG -finline-limit=1000 benchmarkX.cpp -o b && time ./b
#include <iostream>
#include <Eigen/Core>
using namespace std;
using namespace Eigen;
#ifndef MATTYPE
#define MATTYPE MatrixXLd
#endif
#ifndef MATSIZE
#define MATSIZE 400
#endif
#ifndef REPEAT
#define REPEAT 100
#endif
int main(int argc, char *argv[])
{
MATTYPE I = MATTYPE::Ones(MATSIZE,MATSIZE);
MATTYPE m(MATSIZE,MATSIZE);
for(int i = 0; i < MATSIZE; i++) for(int j = 0; j < MATSIZE; j++)
{
m(i,j) = (i+j+1)/(MATSIZE*MATSIZE);
}
for(int a = 0; a < REPEAT; a++)
{
m = I + 0.0001 * (m + m*m);
}
cout << m(0,0) << endl;
return 0;
}
@@ -0,0 +1,35 @@
// g++ -O3 -DNDEBUG benchmarkX.cpp -o benchmarkX && time ./benchmarkX
#include <iostream>
#include <Eigen/Core>
using namespace std;
using namespace Eigen;
#ifndef VECTYPE
#define VECTYPE VectorXLd
#endif
#ifndef VECSIZE
#define VECSIZE 1000000
#endif
#ifndef REPEAT
#define REPEAT 1000
#endif
int main(int argc, char *argv[])
{
VECTYPE I = VECTYPE::Ones(VECSIZE);
VECTYPE m(VECSIZE,1);
for(int i = 0; i < VECSIZE; i++)
{
m[i] = 0.1 * i/VECSIZE;
}
for(int a = 0; a < REPEAT; a++)
{
m = VECTYPE::Ones(VECSIZE) + 0.00005 * (m.cwise().square() + m/4);
}
cout << m[0] << endl;
return 0;
}
@@ -0,0 +1,107 @@
project(BTL)
cmake_minimum_required(VERSION 2.6.2)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${Eigen_SOURCE_DIR}/cmake)
include(MacroOptionalAddSubdirectory)
option(BTL_NOVEC "Disable SSE/Altivec optimizations when possible" OFF)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
string(REGEX MATCH icpc IS_ICPC ${CMAKE_CXX_COMPILER})
if(CMAKE_COMPILER_IS_GNUCXX OR IS_ICPC)
set(CMAKE_CXX_FLAGS "-g0 -O3 -DNDEBUG ${CMAKE_CXX_FLAGS}")
set(CMAKE_Fortran_FLAGS "-g0 -O3 -DNDEBUG ${CMAKE_Fortran_FLAGS}")
if(BTL_NOVEC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEIGEN_DONT_VECTORIZE")
endif(BTL_NOVEC)
endif(CMAKE_COMPILER_IS_GNUCXX OR IS_ICPC)
if(MSVC)
set(CMAKE_CXX_FLAGS " /O2 /Ot /GL /fp:fast -DNDEBUG")
# set(CMAKE_Fortran_FLAGS "-g0 -O3 -DNDEBUG")
if(BTL_NOVEC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEIGEN_DONT_VECTORIZE")
endif(BTL_NOVEC)
endif(MSVC)
if(IS_ICPC)
set(CMAKE_CXX_FLAGS "-fast ${CMAKE_CXX_FLAGS}")
set(CMAKE_Fortran_FLAGS "-fast ${CMAKE_Fortran_FLAGS}")
endif()
include_directories(
${PROJECT_SOURCE_DIR}/actions
${PROJECT_SOURCE_DIR}/generic_bench
${PROJECT_SOURCE_DIR}/generic_bench/utils
${PROJECT_SOURCE_DIR}/libs/STL)
# find_package(MKL)
# if (MKL_FOUND)
# add_definitions(-DHAVE_MKL)
# set(DEFAULT_LIBRARIES ${MKL_LIBRARIES})
# endif ()
find_library(EIGEN_BTL_RT_LIBRARY rt)
# if we cannot find it easily, then we don't need it!
if(NOT EIGEN_BTL_RT_LIBRARY)
set(EIGEN_BTL_RT_LIBRARY "")
endif()
macro(BTL_ADD_BENCH targetname)
foreach(_current_var ${ARGN})
set(_last_var ${_current_var})
endforeach()
set(_sources ${ARGN})
list(LENGTH _sources _argn_length)
list(REMOVE_ITEM _sources ON OFF TRUE FALSE)
list(LENGTH _sources _src_length)
if (${_argn_length} EQUAL ${_src_length})
set(_last_var ON)
endif ()
option(BUILD_${targetname} "Build benchmark ${targetname}" ${_last_var})
if(BUILD_${targetname})
add_executable(${targetname} ${_sources})
add_test(${targetname} "${targetname}")
target_link_libraries(${targetname} ${DEFAULT_LIBRARIES} ${EIGEN_BTL_RT_LIBRARY})
endif(BUILD_${targetname})
endmacro(BTL_ADD_BENCH)
macro(btl_add_target_property target prop value)
if(BUILD_${target})
get_target_property(previous ${target} ${prop})
if(NOT previous)
set(previous "")
endif()
set_target_properties(${target} PROPERTIES ${prop} "${previous} ${value}")
endif()
endmacro()
enable_testing()
add_subdirectory(libs/eigen3)
add_subdirectory(libs/eigen2)
add_subdirectory(libs/tensors)
add_subdirectory(libs/BLAS)
add_subdirectory(libs/ublas)
add_subdirectory(libs/gmm)
add_subdirectory(libs/mtl4)
add_subdirectory(libs/blitz)
add_subdirectory(libs/tvmet)
add_subdirectory(libs/STL)
add_subdirectory(libs/blaze)
add_subdirectory(data)
@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
@@ -0,0 +1,51 @@
if (ACML_LIBRARIES)
set(ACML_FIND_QUIETLY TRUE)
endif ()
find_library(ACML_LIBRARIES
NAMES
acml_mp acml_mv
PATHS
$ENV{ACMLDIR}/lib
$ENV{ACML_DIR}/lib
${LIB_INSTALL_DIR}
)
find_file(ACML_LIBRARIES
NAMES
libacml_mp.so
PATHS
/usr/lib
/usr/lib64
$ENV{ACMLDIR}/lib
${LIB_INSTALL_DIR}
)
if(NOT ACML_LIBRARIES)
message(STATUS "Multi-threaded library not found, looking for single-threaded")
find_library(ACML_LIBRARIES
NAMES
acml acml_mv
PATHS
$ENV{ACMLDIR}/lib
$ENV{ACML_DIR}/lib
${LIB_INSTALL_DIR}
)
find_file(ACML_LIBRARIES
libacml.so libacml_mv.so
PATHS
/usr/lib
/usr/lib64
$ENV{ACMLDIR}/lib
${LIB_INSTALL_DIR}
)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ACML DEFAULT_MSG ACML_LIBRARIES)
mark_as_advanced(ACML_LIBRARIES)
@@ -0,0 +1,31 @@
if (ATLAS_LIBRARIES)
set(ATLAS_FIND_QUIETLY TRUE)
endif ()
find_file(ATLAS_LIB libatlas.so.3 PATHS /usr/lib /usr/lib/atlas /usr/lib64 /usr/lib64/atlas $ENV{ATLASDIR} ${LIB_INSTALL_DIR})
find_library(ATLAS_LIB satlas PATHS $ENV{ATLASDIR} ${LIB_INSTALL_DIR})
find_file(ATLAS_LAPACK NAMES liblapack_atlas.so.3 liblapack.so.3 PATHS /usr/lib /usr/lib/atlas /usr/lib64 /usr/lib64/atlas $ENV{ATLASDIR} ${LIB_INSTALL_DIR})
find_library(ATLAS_LAPACK NAMES lapack_atlas lapack PATHS $ENV{ATLASDIR} ${LIB_INSTALL_DIR})
find_file(ATLAS_F77BLAS libf77blas.so.3 PATHS /usr/lib /usr/lib/atlas /usr/lib64 /usr/lib64/atlas $ENV{ATLASDIR} ${LIB_INSTALL_DIR})
find_library(ATLAS_F77BLAS f77blas PATHS $ENV{ATLASDIR} ${LIB_INSTALL_DIR})
if(ATLAS_LIB AND ATLAS_CBLAS AND ATLAS_LAPACK AND ATLAS_F77BLAS)
set(ATLAS_LIBRARIES ${ATLAS_LAPACK} ${ATLAS_LIB})
# search the default lapack lib link to it
find_file(ATLAS_REFERENCE_LAPACK liblapack.so.3 PATHS /usr/lib /usr/lib64)
find_library(ATLAS_REFERENCE_LAPACK NAMES lapack)
# if(ATLAS_REFERENCE_LAPACK)
# set(ATLAS_LIBRARIES ${ATLAS_LIBRARIES} ${ATLAS_REFERENCE_LAPACK})
# endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ATLAS DEFAULT_MSG ATLAS_LIBRARIES)
mark_as_advanced(ATLAS_LIBRARIES)
@@ -0,0 +1,31 @@
# - Try to find eigen2 headers
# Once done this will define
#
# BLAZE_FOUND - system has blaze lib
# BLAZE_INCLUDE_DIR - the blaze include directory
#
# Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
# Adapted from FindEigen.cmake:
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if (BLAZE_INCLUDE_DIR)
# in cache already
set(BLAZE_FOUND TRUE)
else ()
find_path(BLAZE_INCLUDE_DIR NAMES blaze/Blaze.h
PATHS
${INCLUDE_INSTALL_DIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(BLAZE DEFAULT_MSG BLAZE_INCLUDE_DIR)
mark_as_advanced(BLAZE_INCLUDE_DIR)
endif()
@@ -0,0 +1,40 @@
# - Try to find blitz lib
# Once done this will define
#
# BLITZ_FOUND - system has blitz lib
# BLITZ_INCLUDES - the blitz include directory
# BLITZ_LIBRARIES - The libraries needed to use blitz
# Copyright (c) 2006, Montel Laurent, <montel@kde.org>
# Copyright (c) 2007, Allen Winter, <winter@kde.org>
# Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# include(FindLibraryWithDebug)
if (BLITZ_INCLUDES AND BLITZ_LIBRARIES)
set(Blitz_FIND_QUIETLY TRUE)
endif ()
find_path(BLITZ_INCLUDES
NAMES
blitz/array.h
PATH_SUFFIXES blitz*
PATHS
$ENV{BLITZDIR}/include
${INCLUDE_INSTALL_DIR}
)
find_library(BLITZ_LIBRARIES
blitz
PATHS
$ENV{BLITZDIR}/lib
${LIB_INSTALL_DIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Blitz DEFAULT_MSG
BLITZ_INCLUDES BLITZ_LIBRARIES)
mark_as_advanced(BLITZ_INCLUDES BLITZ_LIBRARIES)
@@ -0,0 +1,35 @@
# include(FindLibraryWithDebug)
if (CBLAS_INCLUDES AND CBLAS_LIBRARIES)
set(CBLAS_FIND_QUIETLY TRUE)
endif ()
find_path(CBLAS_INCLUDES
NAMES
cblas.h
PATHS
$ENV{CBLASDIR}/include
${INCLUDE_INSTALL_DIR}
)
find_library(CBLAS_LIBRARIES
cblas
PATHS
$ENV{CBLASDIR}/lib
${LIB_INSTALL_DIR}
)
find_file(CBLAS_LIBRARIES
libcblas.so.3
PATHS
/usr/lib
/usr/lib64
$ENV{CBLASDIR}/lib
${LIB_INSTALL_DIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CBLAS DEFAULT_MSG
CBLAS_INCLUDES CBLAS_LIBRARIES)
mark_as_advanced(CBLAS_INCLUDES CBLAS_LIBRARIES)
@@ -0,0 +1,17 @@
if (GMM_INCLUDE_DIR)
# in cache already
set(GMM_FOUND TRUE)
else ()
find_path(GMM_INCLUDE_DIR NAMES gmm/gmm.h
PATHS
${INCLUDE_INSTALL_DIR}
${GMM_INCLUDE_PATH}
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMM DEFAULT_MSG GMM_INCLUDE_DIR )
mark_as_advanced(GMM_INCLUDE_DIR)
endif()
@@ -0,0 +1,65 @@
if (MKL_LIBRARIES)
set(MKL_FIND_QUIETLY TRUE)
endif ()
if(CMAKE_MINOR_VERSION GREATER 4)
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
find_library(MKL_LIBRARIES
mkl_core
PATHS
$ENV{MKLLIB}
/opt/intel/mkl/*/lib/em64t
/opt/intel/Compiler/*/*/mkl/lib/em64t
${LIB_INSTALL_DIR}
)
find_library(MKL_GUIDE
guide
PATHS
$ENV{MKLLIB}
/opt/intel/mkl/*/lib/em64t
/opt/intel/Compiler/*/*/mkl/lib/em64t
/opt/intel/Compiler/*/*/lib/intel64
${LIB_INSTALL_DIR}
)
if(MKL_LIBRARIES AND MKL_GUIDE)
set(MKL_LIBRARIES ${MKL_LIBRARIES} mkl_intel_lp64 mkl_sequential ${MKL_GUIDE} pthread)
endif()
else()
find_library(MKL_LIBRARIES
mkl_core
PATHS
$ENV{MKLLIB}
/opt/intel/mkl/*/lib/32
/opt/intel/Compiler/*/*/mkl/lib/32
${LIB_INSTALL_DIR}
)
find_library(MKL_GUIDE
guide
PATHS
$ENV{MKLLIB}
/opt/intel/mkl/*/lib/32
/opt/intel/Compiler/*/*/mkl/lib/32
/opt/intel/Compiler/*/*/lib/intel32
${LIB_INSTALL_DIR}
)
if(MKL_LIBRARIES AND MKL_GUIDE)
set(MKL_LIBRARIES ${MKL_LIBRARIES} mkl_intel mkl_sequential ${MKL_GUIDE} pthread)
endif()
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MKL DEFAULT_MSG MKL_LIBRARIES)
mark_as_advanced(MKL_LIBRARIES)
@@ -0,0 +1,31 @@
# - Try to find eigen2 headers
# Once done this will define
#
# MTL4_FOUND - system has eigen2 lib
# MTL4_INCLUDE_DIR - the eigen2 include directory
#
# Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
# Adapted from FindEigen.cmake:
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if (MTL4_INCLUDE_DIR)
# in cache already
set(MTL4_FOUND TRUE)
else ()
find_path(MTL4_INCLUDE_DIR NAMES boost/numeric/mtl/mtl.hpp
PATHS
${INCLUDE_INSTALL_DIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MTL4 DEFAULT_MSG MTL4_INCLUDE_DIR)
mark_as_advanced(MTL4_INCLUDE_DIR)
endif()
@@ -0,0 +1,17 @@
if (OPENBLAS_LIBRARIES)
set(OPENBLAS_FIND_QUIETLY TRUE)
endif ()
find_file(OPENBLAS_LIBRARIES NAMES libopenblas.so libopenblas.so.0 PATHS /usr/lib /usr/lib64 $ENV{OPENBLASDIR} ${LIB_INSTALL_DIR})
find_library(OPENBLAS_LIBRARIES openblas PATHS $ENV{OPENBLASDIR} ${LIB_INSTALL_DIR})
if(OPENBLAS_LIBRARIES AND CMAKE_COMPILER_IS_GNUCXX)
set(OPENBLAS_LIBRARIES ${OPENBLAS_LIBRARIES} "-lpthread -lgfortran")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OPENBLAS DEFAULT_MSG
OPENBLAS_LIBRARIES)
mark_as_advanced(OPENBLAS_LIBRARIES)
@@ -0,0 +1,60 @@
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME (DEFAULT_MSG|"Custom failure message") VAR1 ... )
#
# This macro is intended to be used in FindXXX.cmake modules files.
# It handles the REQUIRED and QUIET argument to find_package() and
# it also sets the <UPPERCASED_NAME>_FOUND variable.
# The package is found if all variables listed are TRUE.
# Example:
#
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARIES LIBXML2_INCLUDE_DIR)
#
# LibXml2 is considered to be found, if both LIBXML2_LIBRARIES and
# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE.
# If it is not found and REQUIRED was used, it fails with FATAL_ERROR,
# independent whether QUIET was used or not.
#
# If it is found, the location is reported using the VAR1 argument, so
# here a message "Found LibXml2: /usr/lib/libxml2.so" will be printed out.
# If the second argument is DEFAULT_MSG, the message in the failure case will
# be "Could NOT find LibXml2", if you don't like this message you can specify
# your own custom failure message there.
macro(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FAIL_MSG _VAR1 )
if("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
if (${_NAME}_FIND_REQUIRED)
set(_FAIL_MESSAGE "Could not find REQUIRED package ${_NAME}")
else (${_NAME}_FIND_REQUIRED)
set(_FAIL_MESSAGE "Could not find OPTIONAL package ${_NAME}")
endif (${_NAME}_FIND_REQUIRED)
else("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
set(_FAIL_MESSAGE "${_FAIL_MSG}")
endif("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG")
string(TOUPPER ${_NAME} _NAME_UPPER)
set(${_NAME_UPPER}_FOUND TRUE)
if(NOT ${_VAR1})
set(${_NAME_UPPER}_FOUND FALSE)
endif(NOT ${_VAR1})
foreach(_CURRENT_VAR ${ARGN})
if(NOT ${_CURRENT_VAR})
set(${_NAME_UPPER}_FOUND FALSE)
endif(NOT ${_CURRENT_VAR})
endforeach(_CURRENT_VAR)
if (${_NAME_UPPER}_FOUND)
if (NOT ${_NAME}_FIND_QUIETLY)
message(STATUS "Found ${_NAME}: ${${_VAR1}}")
endif (NOT ${_NAME}_FIND_QUIETLY)
else (${_NAME_UPPER}_FOUND)
if (${_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "${_FAIL_MESSAGE}")
else (${_NAME}_FIND_REQUIRED)
if (NOT ${_NAME}_FIND_QUIETLY)
message(STATUS "${_FAIL_MESSAGE}")
endif (NOT ${_NAME}_FIND_QUIETLY)
endif (${_NAME}_FIND_REQUIRED)
endif (${_NAME_UPPER}_FOUND)
endmacro(FIND_PACKAGE_HANDLE_STANDARD_ARGS)
@@ -0,0 +1,32 @@
# - Try to find tvmet headers
# Once done this will define
#
# TVMET_FOUND - system has tvmet lib
# TVMET_INCLUDE_DIR - the tvmet include directory
#
# Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
# Adapted from FindEigen.cmake:
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if (TVMET_INCLUDE_DIR)
# in cache already
set(TVMET_FOUND TRUE)
else ()
find_path(TVMET_INCLUDE_DIR NAMES tvmet/tvmet.h
PATHS
${TVMETDIR}/
${INCLUDE_INSTALL_DIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Tvmet DEFAULT_MSG TVMET_INCLUDE_DIR)
mark_as_advanced(TVMET_INCLUDE_DIR)
endif()
@@ -0,0 +1,31 @@
# - MACRO_OPTIONAL_ADD_SUBDIRECTORY() combines add_subdirectory() with an option()
# MACRO_OPTIONAL_ADD_SUBDIRECTORY( <dir> )
# If you use MACRO_OPTIONAL_ADD_SUBDIRECTORY() instead of add_subdirectory(),
# this will have two effects
# 1 - CMake will not complain if the directory doesn't exist
# This makes sense if you want to distribute just one of the subdirs
# in a source package, e.g. just one of the subdirs in kdeextragear.
# 2 - If the directory exists, it will offer an option to skip the
# subdirectory.
# This is useful if you want to compile only a subset of all
# directories.
# Copyright (c) 2007, Alexander Neundorf, <neundorf@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_OPTIONAL_ADD_SUBDIRECTORY _dir )
get_filename_component(_fullPath ${_dir} ABSOLUTE)
if(EXISTS ${_fullPath})
if(${ARGC} EQUAL 2)
option(BUILD_${_dir} "Build directory ${_dir}" ${ARGV1})
else(${ARGC} EQUAL 2)
option(BUILD_${_dir} "Build directory ${_dir}" TRUE)
endif(${ARGC} EQUAL 2)
if(BUILD_${_dir})
add_subdirectory(${_dir})
endif(BUILD_${_dir})
endif(EXISTS ${_fullPath})
endmacro (MACRO_OPTIONAL_ADD_SUBDIRECTORY)
@@ -0,0 +1,90 @@
//=============================================================================
// File : utilities.h
// Created : mar jun 19 13:18:14 CEST 2001
// Author : Antoine YESSAYAN, Paul RASCLE, EDF
// Project : SALOME
// Copyright : EDF 2001
// $Header$
//=============================================================================
/* --- Definition macros file to print information if _DEBUG_ is defined --- */
# ifndef UTILITIES_H
# define UTILITIES_H
# include <stdlib.h>
//# include <iostream> ok for gcc3.01
# include <iostream>
/* --- INFOS is always defined (without _DEBUG_): to be used for warnings, with release version --- */
# define HEREWEARE cout<<flush ; cerr << __FILE__ << " [" << __LINE__ << "] : " << flush ;
# define INFOS(chain) {HEREWEARE ; cerr << chain << endl ;}
# define PYSCRIPT(chain) {cout<<flush ; cerr << "---PYSCRIPT--- " << chain << endl ;}
/* --- To print date and time of compilation of current source on stdout --- */
# if defined ( __GNUC__ )
# define COMPILER "g++" ;
# elif defined ( __sun )
# define COMPILER "CC" ;
# elif defined ( __KCC )
# define COMPILER "KCC" ;
# elif defined ( __PGI )
# define COMPILER "pgCC" ;
# else
# define COMPILER "undefined" ;
# endif
# ifdef INFOS_COMPILATION
# error INFOS_COMPILATION already defined
# endif
# define INFOS_COMPILATION {\
cerr << flush;\
cout << __FILE__ ;\
cout << " [" << __LINE__ << "] : " ;\
cout << "COMPILED with " << COMPILER ;\
cout << ", " << __DATE__ ; \
cout << " at " << __TIME__ << endl ;\
cout << "\n\n" ;\
cout << flush ;\
}
# ifdef _DEBUG_
/* --- the following MACROS are useful at debug time --- */
# define HERE cout<<flush ; cerr << "- Trace " << __FILE__ << " [" << __LINE__ << "] : " << flush ;
# define SCRUTE(var) HERE ; cerr << #var << "=" << var << endl ;
# define MESSAGE(chain) {HERE ; cerr << chain << endl ;}
# define INTERRUPTION(code) HERE ; cerr << "INTERRUPTION return code= " << code << endl ; exit(code) ;
# ifndef ASSERT
# define ASSERT(condition) if (!(condition)){ HERE ; cerr << "CONDITION " << #condition << " NOT VERIFIED"<< endl ; INTERRUPTION(1) ;}
# endif /* ASSERT */
#define REPERE cout<<flush ; cerr << " --------------" << endl << flush ;
#define BEGIN_OF(chain) {REPERE ; HERE ; cerr << "Begin of: " << chain << endl ; REPERE ; }
#define END_OF(chain) {REPERE ; HERE ; cerr << "Normal end of: " << chain << endl ; REPERE ; }
# else /* ifdef _DEBUG_*/
# define HERE
# define SCRUTE(var)
# define MESSAGE(chain)
# define INTERRUPTION(code)
# ifndef ASSERT
# define ASSERT(condition)
# endif /* ASSERT */
#define REPERE
#define BEGIN_OF(chain)
#define END_OF(chain)
# endif /* ifdef _DEBUG_*/
# endif /* ifndef UTILITIES_H */
@@ -0,0 +1,47 @@
find_package(ATLAS)
if (ATLAS_FOUND)
btl_add_bench(btl_atlas main.cpp)
if(BUILD_btl_atlas)
target_link_libraries(btl_atlas ${ATLAS_LIBRARIES})
set_target_properties(btl_atlas PROPERTIES COMPILE_FLAGS "-DCBLASNAME=ATLAS -DHAS_LAPACK=1")
endif()
endif ()
find_package(MKL)
if (MKL_FOUND)
btl_add_bench(btl_mkl main.cpp)
if(BUILD_btl_mkl)
target_link_libraries(btl_mkl ${MKL_LIBRARIES})
set_target_properties(btl_mkl PROPERTIES COMPILE_FLAGS "-DCBLASNAME=INTEL_MKL -DHAS_LAPACK=1")
endif()
endif ()
find_package(OPENBLAS)
if (OPENBLAS_FOUND)
btl_add_bench(btl_openblas main.cpp)
if(BUILD_btl_openblas)
target_link_libraries(btl_openblas ${OPENBLAS_LIBRARIES} )
set_target_properties(btl_openblas PROPERTIES COMPILE_FLAGS "-DCBLASNAME=OPENBLAS")
endif()
endif ()
find_package(ACML)
if (ACML_FOUND)
btl_add_bench(btl_acml main.cpp)
if(BUILD_btl_acml)
target_link_libraries(btl_acml ${ACML_LIBRARIES} )
set_target_properties(btl_acml PROPERTIES COMPILE_FLAGS "-DCBLASNAME=ACML -DHAS_LAPACK=1")
endif()
endif ()
if(Eigen_SOURCE_DIR AND CMAKE_Fortran_COMPILER_WORKS)
# we are inside Eigen and blas/lapack interface is compilable
include_directories(${Eigen_SOURCE_DIR})
btl_add_bench(btl_eigenblas main.cpp)
if(BUILD_btl_eigenblas)
target_link_libraries(btl_eigenblas eigen_blas eigen_lapack )
set_target_properties(btl_eigenblas PROPERTIES COMPILE_FLAGS "-DCBLASNAME=EigenBLAS")
endif()
endif()
@@ -0,0 +1,675 @@
#ifndef BLAS_H
#define BLAS_H
#define BLASFUNC(FUNC) FUNC##_
#ifdef __WIN64__
typedef long long BLASLONG;
typedef unsigned long long BLASULONG;
#else
typedef long BLASLONG;
typedef unsigned long BLASULONG;
#endif
int BLASFUNC(xerbla)(const char *, int *info, int);
float BLASFUNC(sdot) (int *, float *, int *, float *, int *);
float BLASFUNC(sdsdot)(int *, float *, float *, int *, float *, int *);
double BLASFUNC(dsdot) (int *, float *, int *, float *, int *);
double BLASFUNC(ddot) (int *, double *, int *, double *, int *);
double BLASFUNC(qdot) (int *, double *, int *, double *, int *);
#if defined(F_INTERFACE_GFORT) && !defined(__64BIT__)
int BLASFUNC(cdotu) (int *, float * , int *, float *, int *);
int BLASFUNC(cdotc) (int *, float *, int *, float *, int *);
void BLASFUNC(zdotu) (double *, int *, double *, int *, double *, int *);
void BLASFUNC(zdotc) (double *, int *, double *, int *, double *, int *);
void BLASFUNC(xdotu) (double *, int *, double *, int *, double *, int *);
void BLASFUNC(xdotc) (double *, int *, double *, int *, double *, int *);
#elif defined(F_INTERFACE_F2C) || \
defined(F_INTERFACE_PGI) || \
defined(F_INTERFACE_GFORT) || \
(defined(F_INTERFACE_PATHSCALE) && defined(__64BIT__))
void BLASFUNC(cdotu) (float *, int *, float * , int *, float *, int *);
void BLASFUNC(cdotc) (float *, int *, float *, int *, float *, int *);
void BLASFUNC(zdotu) (double *, int *, double *, int *, double *, int *);
void BLASFUNC(zdotc) (double *, int *, double *, int *, double *, int *);
void BLASFUNC(xdotu) (double *, int *, double *, int *, double *, int *);
void BLASFUNC(xdotc) (double *, int *, double *, int *, double *, int *);
#else
std::complex<float> BLASFUNC(cdotu) (int *, float *, int *, float *, int *);
std::complex<float> BLASFUNC(cdotc) (int *, float *, int *, float *, int *);
std::complex<double> BLASFUNC(zdotu) (int *, double *, int *, double *, int *);
std::complex<double> BLASFUNC(zdotc) (int *, double *, int *, double *, int *);
double BLASFUNC(xdotu) (int *, double *, int *, double *, int *);
double BLASFUNC(xdotc) (int *, double *, int *, double *, int *);
#endif
int BLASFUNC(cdotuw) (int *, float *, int *, float *, int *, float*);
int BLASFUNC(cdotcw) (int *, float *, int *, float *, int *, float*);
int BLASFUNC(zdotuw) (int *, double *, int *, double *, int *, double*);
int BLASFUNC(zdotcw) (int *, double *, int *, double *, int *, double*);
int BLASFUNC(saxpy) (int *, float *, float *, int *, float *, int *);
int BLASFUNC(daxpy) (int *, double *, double *, int *, double *, int *);
int BLASFUNC(qaxpy) (int *, double *, double *, int *, double *, int *);
int BLASFUNC(caxpy) (int *, float *, float *, int *, float *, int *);
int BLASFUNC(zaxpy) (int *, double *, double *, int *, double *, int *);
int BLASFUNC(xaxpy) (int *, double *, double *, int *, double *, int *);
int BLASFUNC(caxpyc)(int *, float *, float *, int *, float *, int *);
int BLASFUNC(zaxpyc)(int *, double *, double *, int *, double *, int *);
int BLASFUNC(xaxpyc)(int *, double *, double *, int *, double *, int *);
int BLASFUNC(scopy) (int *, float *, int *, float *, int *);
int BLASFUNC(dcopy) (int *, double *, int *, double *, int *);
int BLASFUNC(qcopy) (int *, double *, int *, double *, int *);
int BLASFUNC(ccopy) (int *, float *, int *, float *, int *);
int BLASFUNC(zcopy) (int *, double *, int *, double *, int *);
int BLASFUNC(xcopy) (int *, double *, int *, double *, int *);
int BLASFUNC(sswap) (int *, float *, int *, float *, int *);
int BLASFUNC(dswap) (int *, double *, int *, double *, int *);
int BLASFUNC(qswap) (int *, double *, int *, double *, int *);
int BLASFUNC(cswap) (int *, float *, int *, float *, int *);
int BLASFUNC(zswap) (int *, double *, int *, double *, int *);
int BLASFUNC(xswap) (int *, double *, int *, double *, int *);
float BLASFUNC(sasum) (int *, float *, int *);
float BLASFUNC(scasum)(int *, float *, int *);
double BLASFUNC(dasum) (int *, double *, int *);
double BLASFUNC(qasum) (int *, double *, int *);
double BLASFUNC(dzasum)(int *, double *, int *);
double BLASFUNC(qxasum)(int *, double *, int *);
int BLASFUNC(isamax)(int *, float *, int *);
int BLASFUNC(idamax)(int *, double *, int *);
int BLASFUNC(iqamax)(int *, double *, int *);
int BLASFUNC(icamax)(int *, float *, int *);
int BLASFUNC(izamax)(int *, double *, int *);
int BLASFUNC(ixamax)(int *, double *, int *);
int BLASFUNC(ismax) (int *, float *, int *);
int BLASFUNC(idmax) (int *, double *, int *);
int BLASFUNC(iqmax) (int *, double *, int *);
int BLASFUNC(icmax) (int *, float *, int *);
int BLASFUNC(izmax) (int *, double *, int *);
int BLASFUNC(ixmax) (int *, double *, int *);
int BLASFUNC(isamin)(int *, float *, int *);
int BLASFUNC(idamin)(int *, double *, int *);
int BLASFUNC(iqamin)(int *, double *, int *);
int BLASFUNC(icamin)(int *, float *, int *);
int BLASFUNC(izamin)(int *, double *, int *);
int BLASFUNC(ixamin)(int *, double *, int *);
int BLASFUNC(ismin)(int *, float *, int *);
int BLASFUNC(idmin)(int *, double *, int *);
int BLASFUNC(iqmin)(int *, double *, int *);
int BLASFUNC(icmin)(int *, float *, int *);
int BLASFUNC(izmin)(int *, double *, int *);
int BLASFUNC(ixmin)(int *, double *, int *);
float BLASFUNC(samax) (int *, float *, int *);
double BLASFUNC(damax) (int *, double *, int *);
double BLASFUNC(qamax) (int *, double *, int *);
float BLASFUNC(scamax)(int *, float *, int *);
double BLASFUNC(dzamax)(int *, double *, int *);
double BLASFUNC(qxamax)(int *, double *, int *);
float BLASFUNC(samin) (int *, float *, int *);
double BLASFUNC(damin) (int *, double *, int *);
double BLASFUNC(qamin) (int *, double *, int *);
float BLASFUNC(scamin)(int *, float *, int *);
double BLASFUNC(dzamin)(int *, double *, int *);
double BLASFUNC(qxamin)(int *, double *, int *);
float BLASFUNC(smax) (int *, float *, int *);
double BLASFUNC(dmax) (int *, double *, int *);
double BLASFUNC(qmax) (int *, double *, int *);
float BLASFUNC(scmax) (int *, float *, int *);
double BLASFUNC(dzmax) (int *, double *, int *);
double BLASFUNC(qxmax) (int *, double *, int *);
float BLASFUNC(smin) (int *, float *, int *);
double BLASFUNC(dmin) (int *, double *, int *);
double BLASFUNC(qmin) (int *, double *, int *);
float BLASFUNC(scmin) (int *, float *, int *);
double BLASFUNC(dzmin) (int *, double *, int *);
double BLASFUNC(qxmin) (int *, double *, int *);
int BLASFUNC(sscal) (int *, float *, float *, int *);
int BLASFUNC(dscal) (int *, double *, double *, int *);
int BLASFUNC(qscal) (int *, double *, double *, int *);
int BLASFUNC(cscal) (int *, float *, float *, int *);
int BLASFUNC(zscal) (int *, double *, double *, int *);
int BLASFUNC(xscal) (int *, double *, double *, int *);
int BLASFUNC(csscal)(int *, float *, float *, int *);
int BLASFUNC(zdscal)(int *, double *, double *, int *);
int BLASFUNC(xqscal)(int *, double *, double *, int *);
float BLASFUNC(snrm2) (int *, float *, int *);
float BLASFUNC(scnrm2)(int *, float *, int *);
double BLASFUNC(dnrm2) (int *, double *, int *);
double BLASFUNC(qnrm2) (int *, double *, int *);
double BLASFUNC(dznrm2)(int *, double *, int *);
double BLASFUNC(qxnrm2)(int *, double *, int *);
int BLASFUNC(srot) (int *, float *, int *, float *, int *, float *, float *);
int BLASFUNC(drot) (int *, double *, int *, double *, int *, double *, double *);
int BLASFUNC(qrot) (int *, double *, int *, double *, int *, double *, double *);
int BLASFUNC(csrot) (int *, float *, int *, float *, int *, float *, float *);
int BLASFUNC(zdrot) (int *, double *, int *, double *, int *, double *, double *);
int BLASFUNC(xqrot) (int *, double *, int *, double *, int *, double *, double *);
int BLASFUNC(srotg) (float *, float *, float *, float *);
int BLASFUNC(drotg) (double *, double *, double *, double *);
int BLASFUNC(qrotg) (double *, double *, double *, double *);
int BLASFUNC(crotg) (float *, float *, float *, float *);
int BLASFUNC(zrotg) (double *, double *, double *, double *);
int BLASFUNC(xrotg) (double *, double *, double *, double *);
int BLASFUNC(srotmg)(float *, float *, float *, float *, float *);
int BLASFUNC(drotmg)(double *, double *, double *, double *, double *);
int BLASFUNC(srotm) (int *, float *, int *, float *, int *, float *);
int BLASFUNC(drotm) (int *, double *, int *, double *, int *, double *);
int BLASFUNC(qrotm) (int *, double *, int *, double *, int *, double *);
/* Level 2 routines */
int BLASFUNC(sger)(int *, int *, float *, float *, int *,
float *, int *, float *, int *);
int BLASFUNC(dger)(int *, int *, double *, double *, int *,
double *, int *, double *, int *);
int BLASFUNC(qger)(int *, int *, double *, double *, int *,
double *, int *, double *, int *);
int BLASFUNC(cgeru)(int *, int *, float *, float *, int *,
float *, int *, float *, int *);
int BLASFUNC(cgerc)(int *, int *, float *, float *, int *,
float *, int *, float *, int *);
int BLASFUNC(zgeru)(int *, int *, double *, double *, int *,
double *, int *, double *, int *);
int BLASFUNC(zgerc)(int *, int *, double *, double *, int *,
double *, int *, double *, int *);
int BLASFUNC(xgeru)(int *, int *, double *, double *, int *,
double *, int *, double *, int *);
int BLASFUNC(xgerc)(int *, int *, double *, double *, int *,
double *, int *, double *, int *);
int BLASFUNC(sgemv)(char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(dgemv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(qgemv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(cgemv)(char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zgemv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xgemv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(strsv) (char *, char *, char *, int *, float *, int *,
float *, int *);
int BLASFUNC(dtrsv) (char *, char *, char *, int *, double *, int *,
double *, int *);
int BLASFUNC(qtrsv) (char *, char *, char *, int *, double *, int *,
double *, int *);
int BLASFUNC(ctrsv) (char *, char *, char *, int *, float *, int *,
float *, int *);
int BLASFUNC(ztrsv) (char *, char *, char *, int *, double *, int *,
double *, int *);
int BLASFUNC(xtrsv) (char *, char *, char *, int *, double *, int *,
double *, int *);
int BLASFUNC(stpsv) (char *, char *, char *, int *, float *, float *, int *);
int BLASFUNC(dtpsv) (char *, char *, char *, int *, double *, double *, int *);
int BLASFUNC(qtpsv) (char *, char *, char *, int *, double *, double *, int *);
int BLASFUNC(ctpsv) (char *, char *, char *, int *, float *, float *, int *);
int BLASFUNC(ztpsv) (char *, char *, char *, int *, double *, double *, int *);
int BLASFUNC(xtpsv) (char *, char *, char *, int *, double *, double *, int *);
int BLASFUNC(strmv) (char *, char *, char *, int *, float *, int *,
float *, int *);
int BLASFUNC(dtrmv) (char *, char *, char *, int *, double *, int *,
double *, int *);
int BLASFUNC(qtrmv) (char *, char *, char *, int *, double *, int *,
double *, int *);
int BLASFUNC(ctrmv) (char *, char *, char *, int *, float *, int *,
float *, int *);
int BLASFUNC(ztrmv) (char *, char *, char *, int *, double *, int *,
double *, int *);
int BLASFUNC(xtrmv) (char *, char *, char *, int *, double *, int *,
double *, int *);
int BLASFUNC(stpmv) (char *, char *, char *, int *, float *, float *, int *);
int BLASFUNC(dtpmv) (char *, char *, char *, int *, double *, double *, int *);
int BLASFUNC(qtpmv) (char *, char *, char *, int *, double *, double *, int *);
int BLASFUNC(ctpmv) (char *, char *, char *, int *, float *, float *, int *);
int BLASFUNC(ztpmv) (char *, char *, char *, int *, double *, double *, int *);
int BLASFUNC(xtpmv) (char *, char *, char *, int *, double *, double *, int *);
int BLASFUNC(stbmv) (char *, char *, char *, int *, int *, float *, int *, float *, int *);
int BLASFUNC(dtbmv) (char *, char *, char *, int *, int *, double *, int *, double *, int *);
int BLASFUNC(qtbmv) (char *, char *, char *, int *, int *, double *, int *, double *, int *);
int BLASFUNC(ctbmv) (char *, char *, char *, int *, int *, float *, int *, float *, int *);
int BLASFUNC(ztbmv) (char *, char *, char *, int *, int *, double *, int *, double *, int *);
int BLASFUNC(xtbmv) (char *, char *, char *, int *, int *, double *, int *, double *, int *);
int BLASFUNC(stbsv) (char *, char *, char *, int *, int *, float *, int *, float *, int *);
int BLASFUNC(dtbsv) (char *, char *, char *, int *, int *, double *, int *, double *, int *);
int BLASFUNC(qtbsv) (char *, char *, char *, int *, int *, double *, int *, double *, int *);
int BLASFUNC(ctbsv) (char *, char *, char *, int *, int *, float *, int *, float *, int *);
int BLASFUNC(ztbsv) (char *, char *, char *, int *, int *, double *, int *, double *, int *);
int BLASFUNC(xtbsv) (char *, char *, char *, int *, int *, double *, int *, double *, int *);
int BLASFUNC(ssymv) (char *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(dsymv) (char *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(qsymv) (char *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(csymv) (char *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zsymv) (char *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xsymv) (char *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(sspmv) (char *, int *, float *, float *,
float *, int *, float *, float *, int *);
int BLASFUNC(dspmv) (char *, int *, double *, double *,
double *, int *, double *, double *, int *);
int BLASFUNC(qspmv) (char *, int *, double *, double *,
double *, int *, double *, double *, int *);
int BLASFUNC(cspmv) (char *, int *, float *, float *,
float *, int *, float *, float *, int *);
int BLASFUNC(zspmv) (char *, int *, double *, double *,
double *, int *, double *, double *, int *);
int BLASFUNC(xspmv) (char *, int *, double *, double *,
double *, int *, double *, double *, int *);
int BLASFUNC(ssyr) (char *, int *, float *, float *, int *,
float *, int *);
int BLASFUNC(dsyr) (char *, int *, double *, double *, int *,
double *, int *);
int BLASFUNC(qsyr) (char *, int *, double *, double *, int *,
double *, int *);
int BLASFUNC(csyr) (char *, int *, float *, float *, int *,
float *, int *);
int BLASFUNC(zsyr) (char *, int *, double *, double *, int *,
double *, int *);
int BLASFUNC(xsyr) (char *, int *, double *, double *, int *,
double *, int *);
int BLASFUNC(ssyr2) (char *, int *, float *,
float *, int *, float *, int *, float *, int *);
int BLASFUNC(dsyr2) (char *, int *, double *,
double *, int *, double *, int *, double *, int *);
int BLASFUNC(qsyr2) (char *, int *, double *,
double *, int *, double *, int *, double *, int *);
int BLASFUNC(csyr2) (char *, int *, float *,
float *, int *, float *, int *, float *, int *);
int BLASFUNC(zsyr2) (char *, int *, double *,
double *, int *, double *, int *, double *, int *);
int BLASFUNC(xsyr2) (char *, int *, double *,
double *, int *, double *, int *, double *, int *);
int BLASFUNC(sspr) (char *, int *, float *, float *, int *,
float *);
int BLASFUNC(dspr) (char *, int *, double *, double *, int *,
double *);
int BLASFUNC(qspr) (char *, int *, double *, double *, int *,
double *);
int BLASFUNC(cspr) (char *, int *, float *, float *, int *,
float *);
int BLASFUNC(zspr) (char *, int *, double *, double *, int *,
double *);
int BLASFUNC(xspr) (char *, int *, double *, double *, int *,
double *);
int BLASFUNC(sspr2) (char *, int *, float *,
float *, int *, float *, int *, float *);
int BLASFUNC(dspr2) (char *, int *, double *,
double *, int *, double *, int *, double *);
int BLASFUNC(qspr2) (char *, int *, double *,
double *, int *, double *, int *, double *);
int BLASFUNC(cspr2) (char *, int *, float *,
float *, int *, float *, int *, float *);
int BLASFUNC(zspr2) (char *, int *, double *,
double *, int *, double *, int *, double *);
int BLASFUNC(xspr2) (char *, int *, double *,
double *, int *, double *, int *, double *);
int BLASFUNC(cher) (char *, int *, float *, float *, int *,
float *, int *);
int BLASFUNC(zher) (char *, int *, double *, double *, int *,
double *, int *);
int BLASFUNC(xher) (char *, int *, double *, double *, int *,
double *, int *);
int BLASFUNC(chpr) (char *, int *, float *, float *, int *, float *);
int BLASFUNC(zhpr) (char *, int *, double *, double *, int *, double *);
int BLASFUNC(xhpr) (char *, int *, double *, double *, int *, double *);
int BLASFUNC(cher2) (char *, int *, float *,
float *, int *, float *, int *, float *, int *);
int BLASFUNC(zher2) (char *, int *, double *,
double *, int *, double *, int *, double *, int *);
int BLASFUNC(xher2) (char *, int *, double *,
double *, int *, double *, int *, double *, int *);
int BLASFUNC(chpr2) (char *, int *, float *,
float *, int *, float *, int *, float *);
int BLASFUNC(zhpr2) (char *, int *, double *,
double *, int *, double *, int *, double *);
int BLASFUNC(xhpr2) (char *, int *, double *,
double *, int *, double *, int *, double *);
int BLASFUNC(chemv) (char *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zhemv) (char *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xhemv) (char *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(chpmv) (char *, int *, float *, float *,
float *, int *, float *, float *, int *);
int BLASFUNC(zhpmv) (char *, int *, double *, double *,
double *, int *, double *, double *, int *);
int BLASFUNC(xhpmv) (char *, int *, double *, double *,
double *, int *, double *, double *, int *);
int BLASFUNC(snorm)(char *, int *, int *, float *, int *);
int BLASFUNC(dnorm)(char *, int *, int *, double *, int *);
int BLASFUNC(cnorm)(char *, int *, int *, float *, int *);
int BLASFUNC(znorm)(char *, int *, int *, double *, int *);
int BLASFUNC(sgbmv)(char *, int *, int *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(dgbmv)(char *, int *, int *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(qgbmv)(char *, int *, int *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(cgbmv)(char *, int *, int *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zgbmv)(char *, int *, int *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xgbmv)(char *, int *, int *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(ssbmv)(char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(dsbmv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(qsbmv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(csbmv)(char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zsbmv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xsbmv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(chbmv)(char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zhbmv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xhbmv)(char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
/* Level 3 routines */
int BLASFUNC(sgemm)(char *, char *, int *, int *, int *, float *,
float *, int *, float *, int *, float *, float *, int *);
int BLASFUNC(dgemm)(char *, char *, int *, int *, int *, double *,
double *, int *, double *, int *, double *, double *, int *);
int BLASFUNC(qgemm)(char *, char *, int *, int *, int *, double *,
double *, int *, double *, int *, double *, double *, int *);
int BLASFUNC(cgemm)(char *, char *, int *, int *, int *, float *,
float *, int *, float *, int *, float *, float *, int *);
int BLASFUNC(zgemm)(char *, char *, int *, int *, int *, double *,
double *, int *, double *, int *, double *, double *, int *);
int BLASFUNC(xgemm)(char *, char *, int *, int *, int *, double *,
double *, int *, double *, int *, double *, double *, int *);
int BLASFUNC(cgemm3m)(char *, char *, int *, int *, int *, float *,
float *, int *, float *, int *, float *, float *, int *);
int BLASFUNC(zgemm3m)(char *, char *, int *, int *, int *, double *,
double *, int *, double *, int *, double *, double *, int *);
int BLASFUNC(xgemm3m)(char *, char *, int *, int *, int *, double *,
double *, int *, double *, int *, double *, double *, int *);
int BLASFUNC(sge2mm)(char *, char *, char *, int *, int *,
float *, float *, int *, float *, int *,
float *, float *, int *);
int BLASFUNC(dge2mm)(char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *,
double *, double *, int *);
int BLASFUNC(cge2mm)(char *, char *, char *, int *, int *,
float *, float *, int *, float *, int *,
float *, float *, int *);
int BLASFUNC(zge2mm)(char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *,
double *, double *, int *);
int BLASFUNC(strsm)(char *, char *, char *, char *, int *, int *,
float *, float *, int *, float *, int *);
int BLASFUNC(dtrsm)(char *, char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *);
int BLASFUNC(qtrsm)(char *, char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *);
int BLASFUNC(ctrsm)(char *, char *, char *, char *, int *, int *,
float *, float *, int *, float *, int *);
int BLASFUNC(ztrsm)(char *, char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *);
int BLASFUNC(xtrsm)(char *, char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *);
int BLASFUNC(strmm)(char *, char *, char *, char *, int *, int *,
float *, float *, int *, float *, int *);
int BLASFUNC(dtrmm)(char *, char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *);
int BLASFUNC(qtrmm)(char *, char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *);
int BLASFUNC(ctrmm)(char *, char *, char *, char *, int *, int *,
float *, float *, int *, float *, int *);
int BLASFUNC(ztrmm)(char *, char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *);
int BLASFUNC(xtrmm)(char *, char *, char *, char *, int *, int *,
double *, double *, int *, double *, int *);
int BLASFUNC(ssymm)(char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(dsymm)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(qsymm)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(csymm)(char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zsymm)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xsymm)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(csymm3m)(char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zsymm3m)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xsymm3m)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(ssyrk)(char *, char *, int *, int *, float *, float *, int *,
float *, float *, int *);
int BLASFUNC(dsyrk)(char *, char *, int *, int *, double *, double *, int *,
double *, double *, int *);
int BLASFUNC(qsyrk)(char *, char *, int *, int *, double *, double *, int *,
double *, double *, int *);
int BLASFUNC(csyrk)(char *, char *, int *, int *, float *, float *, int *,
float *, float *, int *);
int BLASFUNC(zsyrk)(char *, char *, int *, int *, double *, double *, int *,
double *, double *, int *);
int BLASFUNC(xsyrk)(char *, char *, int *, int *, double *, double *, int *,
double *, double *, int *);
int BLASFUNC(ssyr2k)(char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(dsyr2k)(char *, char *, int *, int *, double *, double *, int *,
double*, int *, double *, double *, int *);
int BLASFUNC(qsyr2k)(char *, char *, int *, int *, double *, double *, int *,
double*, int *, double *, double *, int *);
int BLASFUNC(csyr2k)(char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zsyr2k)(char *, char *, int *, int *, double *, double *, int *,
double*, int *, double *, double *, int *);
int BLASFUNC(xsyr2k)(char *, char *, int *, int *, double *, double *, int *,
double*, int *, double *, double *, int *);
int BLASFUNC(chemm)(char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zhemm)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xhemm)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(chemm3m)(char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zhemm3m)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(xhemm3m)(char *, char *, int *, int *, double *, double *, int *,
double *, int *, double *, double *, int *);
int BLASFUNC(cherk)(char *, char *, int *, int *, float *, float *, int *,
float *, float *, int *);
int BLASFUNC(zherk)(char *, char *, int *, int *, double *, double *, int *,
double *, double *, int *);
int BLASFUNC(xherk)(char *, char *, int *, int *, double *, double *, int *,
double *, double *, int *);
int BLASFUNC(cher2k)(char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zher2k)(char *, char *, int *, int *, double *, double *, int *,
double*, int *, double *, double *, int *);
int BLASFUNC(xher2k)(char *, char *, int *, int *, double *, double *, int *,
double*, int *, double *, double *, int *);
int BLASFUNC(cher2m)(char *, char *, char *, int *, int *, float *, float *, int *,
float *, int *, float *, float *, int *);
int BLASFUNC(zher2m)(char *, char *, char *, int *, int *, double *, double *, int *,
double*, int *, double *, double *, int *);
int BLASFUNC(xher2m)(char *, char *, char *, int *, int *, double *, double *, int *,
double*, int *, double *, double *, int *);
int BLASFUNC(sgemt)(char *, int *, int *, float *, float *, int *,
float *, int *);
int BLASFUNC(dgemt)(char *, int *, int *, double *, double *, int *,
double *, int *);
int BLASFUNC(cgemt)(char *, int *, int *, float *, float *, int *,
float *, int *);
int BLASFUNC(zgemt)(char *, int *, int *, double *, double *, int *,
double *, int *);
int BLASFUNC(sgema)(char *, char *, int *, int *, float *,
float *, int *, float *, float *, int *, float *, int *);
int BLASFUNC(dgema)(char *, char *, int *, int *, double *,
double *, int *, double*, double *, int *, double*, int *);
int BLASFUNC(cgema)(char *, char *, int *, int *, float *,
float *, int *, float *, float *, int *, float *, int *);
int BLASFUNC(zgema)(char *, char *, int *, int *, double *,
double *, int *, double*, double *, int *, double*, int *);
int BLASFUNC(sgems)(char *, char *, int *, int *, float *,
float *, int *, float *, float *, int *, float *, int *);
int BLASFUNC(dgems)(char *, char *, int *, int *, double *,
double *, int *, double*, double *, int *, double*, int *);
int BLASFUNC(cgems)(char *, char *, int *, int *, float *,
float *, int *, float *, float *, int *, float *, int *);
int BLASFUNC(zgems)(char *, char *, int *, int *, double *,
double *, int *, double*, double *, int *, double*, int *);
int BLASFUNC(sgetf2)(int *, int *, float *, int *, int *, int *);
int BLASFUNC(dgetf2)(int *, int *, double *, int *, int *, int *);
int BLASFUNC(qgetf2)(int *, int *, double *, int *, int *, int *);
int BLASFUNC(cgetf2)(int *, int *, float *, int *, int *, int *);
int BLASFUNC(zgetf2)(int *, int *, double *, int *, int *, int *);
int BLASFUNC(xgetf2)(int *, int *, double *, int *, int *, int *);
int BLASFUNC(sgetrf)(int *, int *, float *, int *, int *, int *);
int BLASFUNC(dgetrf)(int *, int *, double *, int *, int *, int *);
int BLASFUNC(qgetrf)(int *, int *, double *, int *, int *, int *);
int BLASFUNC(cgetrf)(int *, int *, float *, int *, int *, int *);
int BLASFUNC(zgetrf)(int *, int *, double *, int *, int *, int *);
int BLASFUNC(xgetrf)(int *, int *, double *, int *, int *, int *);
int BLASFUNC(slaswp)(int *, float *, int *, int *, int *, int *, int *);
int BLASFUNC(dlaswp)(int *, double *, int *, int *, int *, int *, int *);
int BLASFUNC(qlaswp)(int *, double *, int *, int *, int *, int *, int *);
int BLASFUNC(claswp)(int *, float *, int *, int *, int *, int *, int *);
int BLASFUNC(zlaswp)(int *, double *, int *, int *, int *, int *, int *);
int BLASFUNC(xlaswp)(int *, double *, int *, int *, int *, int *, int *);
int BLASFUNC(sgetrs)(char *, int *, int *, float *, int *, int *, float *, int *, int *);
int BLASFUNC(dgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *);
int BLASFUNC(qgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *);
int BLASFUNC(cgetrs)(char *, int *, int *, float *, int *, int *, float *, int *, int *);
int BLASFUNC(zgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *);
int BLASFUNC(xgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *);
int BLASFUNC(sgesv)(int *, int *, float *, int *, int *, float *, int *, int *);
int BLASFUNC(dgesv)(int *, int *, double *, int *, int *, double*, int *, int *);
int BLASFUNC(qgesv)(int *, int *, double *, int *, int *, double*, int *, int *);
int BLASFUNC(cgesv)(int *, int *, float *, int *, int *, float *, int *, int *);
int BLASFUNC(zgesv)(int *, int *, double *, int *, int *, double*, int *, int *);
int BLASFUNC(xgesv)(int *, int *, double *, int *, int *, double*, int *, int *);
int BLASFUNC(spotf2)(char *, int *, float *, int *, int *);
int BLASFUNC(dpotf2)(char *, int *, double *, int *, int *);
int BLASFUNC(qpotf2)(char *, int *, double *, int *, int *);
int BLASFUNC(cpotf2)(char *, int *, float *, int *, int *);
int BLASFUNC(zpotf2)(char *, int *, double *, int *, int *);
int BLASFUNC(xpotf2)(char *, int *, double *, int *, int *);
int BLASFUNC(spotrf)(char *, int *, float *, int *, int *);
int BLASFUNC(dpotrf)(char *, int *, double *, int *, int *);
int BLASFUNC(qpotrf)(char *, int *, double *, int *, int *);
int BLASFUNC(cpotrf)(char *, int *, float *, int *, int *);
int BLASFUNC(zpotrf)(char *, int *, double *, int *, int *);
int BLASFUNC(xpotrf)(char *, int *, double *, int *, int *);
int BLASFUNC(slauu2)(char *, int *, float *, int *, int *);
int BLASFUNC(dlauu2)(char *, int *, double *, int *, int *);
int BLASFUNC(qlauu2)(char *, int *, double *, int *, int *);
int BLASFUNC(clauu2)(char *, int *, float *, int *, int *);
int BLASFUNC(zlauu2)(char *, int *, double *, int *, int *);
int BLASFUNC(xlauu2)(char *, int *, double *, int *, int *);
int BLASFUNC(slauum)(char *, int *, float *, int *, int *);
int BLASFUNC(dlauum)(char *, int *, double *, int *, int *);
int BLASFUNC(qlauum)(char *, int *, double *, int *, int *);
int BLASFUNC(clauum)(char *, int *, float *, int *, int *);
int BLASFUNC(zlauum)(char *, int *, double *, int *, int *);
int BLASFUNC(xlauum)(char *, int *, double *, int *, int *);
int BLASFUNC(strti2)(char *, char *, int *, float *, int *, int *);
int BLASFUNC(dtrti2)(char *, char *, int *, double *, int *, int *);
int BLASFUNC(qtrti2)(char *, char *, int *, double *, int *, int *);
int BLASFUNC(ctrti2)(char *, char *, int *, float *, int *, int *);
int BLASFUNC(ztrti2)(char *, char *, int *, double *, int *, int *);
int BLASFUNC(xtrti2)(char *, char *, int *, double *, int *, int *);
int BLASFUNC(strtri)(char *, char *, int *, float *, int *, int *);
int BLASFUNC(dtrtri)(char *, char *, int *, double *, int *, int *);
int BLASFUNC(qtrtri)(char *, char *, int *, double *, int *, int *);
int BLASFUNC(ctrtri)(char *, char *, int *, float *, int *, int *);
int BLASFUNC(ztrtri)(char *, char *, int *, double *, int *, int *);
int BLASFUNC(xtrtri)(char *, char *, int *, double *, int *, int *);
int BLASFUNC(spotri)(char *, int *, float *, int *, int *);
int BLASFUNC(dpotri)(char *, int *, double *, int *, int *);
int BLASFUNC(qpotri)(char *, int *, double *, int *, int *);
int BLASFUNC(cpotri)(char *, int *, float *, int *, int *);
int BLASFUNC(zpotri)(char *, int *, double *, int *, int *);
int BLASFUNC(xpotri)(char *, int *, double *, int *, int *);
#endif
@@ -0,0 +1,73 @@
#ifndef BTL_C_INTERFACE_BASE_H
#define BTL_C_INTERFACE_BASE_H
#include "utilities.h"
#include <vector>
template<class real> class c_interface_base
{
public:
typedef real real_type;
typedef std::vector<real> stl_vector;
typedef std::vector<stl_vector > stl_matrix;
typedef real* gene_matrix;
typedef real* gene_vector;
static void free_matrix(gene_matrix & A, int /*N*/){
delete[] A;
}
static void free_vector(gene_vector & B){
delete[] B;
}
static inline void matrix_from_stl(gene_matrix & A, stl_matrix & A_stl){
int N = A_stl.size();
A = new real[N*N];
for (int j=0;j<N;j++)
for (int i=0;i<N;i++)
A[i+N*j] = A_stl[j][i];
}
static inline void vector_from_stl(gene_vector & B, stl_vector & B_stl){
int N = B_stl.size();
B = new real[N];
for (int i=0;i<N;i++)
B[i] = B_stl[i];
}
static inline void vector_to_stl(gene_vector & B, stl_vector & B_stl){
int N = B_stl.size();
for (int i=0;i<N;i++)
B_stl[i] = B[i];
}
static inline void matrix_to_stl(gene_matrix & A, stl_matrix & A_stl){
int N = A_stl.size();
for (int j=0;j<N;j++){
A_stl[j].resize(N);
for (int i=0;i<N;i++)
A_stl[j][i] = A[i+N*j];
}
}
static inline void copy_vector(const gene_vector & source, gene_vector & cible, int N){
for (int i=0;i<N;i++)
cible[i]=source[i];
}
static inline void copy_matrix(const gene_matrix & source, gene_matrix & cible, int N){
for (int j=0;j<N;j++){
for (int i=0;i<N;i++){
cible[i+N*j] = source[i+N*j];
}
}
}
};
#endif
@@ -0,0 +1,73 @@
//=====================================================
// File : main.cpp
// Author : L. Plagne <laurent.plagne@edf.fr)>
// Copyright (C) EDF R&D, lun sep 30 14:23:28 CEST 2002
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "blas_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
#include "action_cholesky.hh"
#include "action_lu_decomp.hh"
#include "action_partial_lu.hh"
#include "action_trisolve_matrix.hh"
#ifdef HAS_LAPACK
#include "action_hessenberg.hh"
#endif
BTL_MAIN;
int main()
{
bench<Action_axpy<blas_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<blas_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_matrix_vector_product<blas_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<blas_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_symv<blas_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_syr2<blas_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_ger<blas_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_rot<blas_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_matrix_matrix_product<blas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_ata_product<blas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_aat_product<blas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_trisolve<blas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_trisolve_matrix<blas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_trmm<blas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_cholesky<blas_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
bench<Action_partial_lu<blas_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
#ifdef HAS_LAPACK
// bench<Action_lu_decomp<blas_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
bench<Action_hessenberg<blas_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
bench<Action_tridiagonalization<blas_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
#endif
//bench<Action_lu_solve<blas_LU_solve_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
return 0;
}
@@ -0,0 +1,2 @@
btl_add_bench(btl_STL main.cpp OFF)
@@ -0,0 +1,42 @@
//=====================================================
// File : main.cpp
// Author : L. Plagne <laurent.plagne@edf.fr)>
// Copyright (C) EDF R&D, lun sep 30 14:23:23 CEST 2002
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "STL_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_axpy<STL_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<STL_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_matrix_vector_product<STL_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<STL_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_symv<STL_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_syr2<STL_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_matrix_matrix_product<STL_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_ata_product<STL_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_aat_product<STL_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,13 @@
find_package(BLAZE)
find_package(Boost COMPONENTS system)
if (BLAZE_FOUND AND Boost_FOUND)
include_directories(${BLAZE_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
btl_add_bench(btl_blaze main.cpp)
# Note: The newest blaze version requires C++14.
# Ideally, we should set this depending on the version of Blaze we found
set_property(TARGET btl_blaze PROPERTY CXX_STANDARD 14)
if(BUILD_btl_blaze)
target_link_libraries(btl_blaze ${Boost_LIBRARIES})
endif()
endif ()
@@ -0,0 +1,40 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "blaze_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_axpy<blaze_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<blaze_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_matrix_vector_product<blaze_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<blaze_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_matrix_matrix_product<blaze_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_ata_product<blaze_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_aat_product<blaze_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,17 @@
find_package(Blitz)
if (BLITZ_FOUND)
include_directories(${BLITZ_INCLUDES})
btl_add_bench(btl_blitz btl_blitz.cpp)
if (BUILD_btl_blitz)
target_link_libraries(btl_blitz ${BLITZ_LIBRARIES})
endif ()
btl_add_bench(btl_tiny_blitz btl_tiny_blitz.cpp OFF)
if (BUILD_btl_tiny_blitz)
target_link_libraries(btl_tiny_blitz ${BLITZ_LIBRARIES})
endif ()
endif ()
@@ -0,0 +1,51 @@
//=====================================================
// File : main.cpp
// Author : L. Plagne <laurent.plagne@edf.fr)>
// Copyright (C) EDF R&D, lun sep 30 14:23:30 CEST 2002
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "blitz_interface.hh"
#include "blitz_LU_solve_interface.hh"
#include "bench.hh"
#include "action_matrix_vector_product.hh"
#include "action_matrix_matrix_product.hh"
#include "action_axpy.hh"
#include "action_lu_solve.hh"
#include "action_ata_product.hh"
#include "action_aat_product.hh"
#include "action_atv_product.hh"
BTL_MAIN;
int main()
{
bench<Action_matrix_vector_product<blitz_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<blitz_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_matrix_matrix_product<blitz_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_ata_product<blitz_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_aat_product<blitz_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_axpy<blitz_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
//bench<Action_lu_solve<blitz_LU_solve_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
return 0;
}
@@ -0,0 +1,38 @@
//=====================================================
// File : main.cpp
// Author : L. Plagne <laurent.plagne@edf.fr)>
// Copyright (C) EDF R&D, lun sep 30 14:23:30 CEST 2002
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "tiny_blitz_interface.hh"
#include "static/bench_static.hh"
#include "action_matrix_vector_product.hh"
#include "action_matrix_matrix_product.hh"
#include "action_axpy.hh"
BTL_MAIN;
int main()
{
bench_static<Action_axpy,tiny_blitz_interface>();
bench_static<Action_matrix_matrix_product,tiny_blitz_interface>();
bench_static<Action_matrix_vector_product,tiny_blitz_interface>();
return 0;
}
@@ -0,0 +1,19 @@
find_package(Eigen2)
if(EIGEN2_FOUND)
include_directories(BEFORE ${EIGEN2_INCLUDE_DIR})
btl_add_bench(btl_eigen2_linear main_linear.cpp)
btl_add_bench(btl_eigen2_vecmat main_vecmat.cpp)
btl_add_bench(btl_eigen2_matmat main_matmat.cpp)
btl_add_bench(btl_eigen2_adv main_adv.cpp )
btl_add_target_property(btl_eigen2_linear COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=eigen2")
btl_add_target_property(btl_eigen2_vecmat COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=eigen2")
btl_add_target_property(btl_eigen2_matmat COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=eigen2")
btl_add_target_property(btl_eigen2_adv COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=eigen2")
btl_add_bench(btl_tiny_eigen2 btl_tiny_eigen2.cpp OFF)
endif() # EIGEN2_FOUND
@@ -0,0 +1,46 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen3_interface.hh"
#include "static/bench_static.hh"
#include "action_matrix_vector_product.hh"
#include "action_matrix_matrix_product.hh"
#include "action_axpy.hh"
#include "action_lu_solve.hh"
#include "action_ata_product.hh"
#include "action_aat_product.hh"
#include "action_atv_product.hh"
#include "action_cholesky.hh"
#include "action_trisolve.hh"
BTL_MAIN;
int main()
{
bench_static<Action_axpy,eigen2_interface>();
bench_static<Action_matrix_matrix_product,eigen2_interface>();
bench_static<Action_matrix_vector_product,eigen2_interface>();
bench_static<Action_atv_product,eigen2_interface>();
bench_static<Action_cholesky,eigen2_interface>();
bench_static<Action_trisolve,eigen2_interface>();
return 0;
}
@@ -0,0 +1,44 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen2_interface.hh"
#include "bench.hh"
#include "action_trisolve.hh"
#include "action_trisolve_matrix.hh"
#include "action_cholesky.hh"
#include "action_hessenberg.hh"
#include "action_lu_decomp.hh"
// #include "action_partial_lu.hh"
BTL_MAIN;
int main()
{
bench<Action_trisolve<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_trisolve_matrix<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_cholesky<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_lu_decomp<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_partial_lu<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_hessenberg<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_tridiagonalization<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,34 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen2_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_axpy<eigen2_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<eigen2_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
return 0;
}
@@ -0,0 +1,35 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen2_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_matrix_matrix_product<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_ata_product<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_aat_product<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_trmm<eigen2_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,36 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen2_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_matrix_vector_product<eigen2_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<eigen2_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
// bench<Action_symv<eigen2_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
// bench<Action_syr2<eigen2_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
// bench<Action_ger<eigen2_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
return 0;
}
@@ -0,0 +1,65 @@
if((NOT EIGEN3_INCLUDE_DIR) AND Eigen_SOURCE_DIR)
# unless EIGEN3_INCLUDE_DIR is defined, let's use current Eigen version
set(EIGEN3_INCLUDE_DIR ${Eigen_SOURCE_DIR})
set(EIGEN3_FOUND TRUE)
else()
find_package(Eigen3)
endif()
if (EIGEN3_FOUND)
include_directories(${EIGEN3_INCLUDE_DIR})
btl_add_bench(btl_eigen3_linear main_linear.cpp)
btl_add_bench(btl_eigen3_vecmat main_vecmat.cpp)
btl_add_bench(btl_eigen3_matmat main_matmat.cpp)
btl_add_bench(btl_eigen3_adv main_adv.cpp )
btl_add_target_property(btl_eigen3_linear COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=eigen3")
btl_add_target_property(btl_eigen3_vecmat COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=eigen3")
btl_add_target_property(btl_eigen3_matmat COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=eigen3")
btl_add_target_property(btl_eigen3_adv COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=eigen3")
option(BTL_BENCH_NOGCCVEC "also bench Eigen explicit vec without GCC's auto vec" OFF)
if(CMAKE_COMPILER_IS_GNUCXX AND BTL_BENCH_NOGCCVEC)
btl_add_bench(btl_eigen3_nogccvec_linear main_linear.cpp)
btl_add_bench(btl_eigen3_nogccvec_vecmat main_vecmat.cpp)
btl_add_bench(btl_eigen3_nogccvec_matmat main_matmat.cpp)
btl_add_bench(btl_eigen3_nogccvec_adv main_adv.cpp )
btl_add_target_property(btl_eigen3_nogccvec_linear COMPILE_FLAGS "-fno-exceptions -fno-tree-vectorize -DBTL_PREFIX=eigen3_nogccvec")
btl_add_target_property(btl_eigen3_nogccvec_vecmat COMPILE_FLAGS "-fno-exceptions -fno-tree-vectorize -DBTL_PREFIX=eigen3_nogccvec")
btl_add_target_property(btl_eigen3_nogccvec_matmat COMPILE_FLAGS "-fno-exceptions -fno-tree-vectorize -DBTL_PREFIX=eigen3_nogccvec")
btl_add_target_property(btl_eigen3_nogccvec_adv COMPILE_FLAGS "-fno-exceptions -fno-tree-vectorize -DBTL_PREFIX=eigen3_nogccvec")
endif()
if(NOT BTL_NOVEC)
btl_add_bench(btl_eigen3_novec_linear main_linear.cpp OFF)
btl_add_bench(btl_eigen3_novec_vecmat main_vecmat.cpp OFF)
btl_add_bench(btl_eigen3_novec_matmat main_matmat.cpp OFF)
btl_add_bench(btl_eigen3_novec_adv main_adv.cpp OFF)
btl_add_target_property(btl_eigen3_novec_linear COMPILE_FLAGS "-fno-exceptions -DEIGEN_DONT_VECTORIZE -DBTL_PREFIX=eigen3_novec")
btl_add_target_property(btl_eigen3_novec_vecmat COMPILE_FLAGS "-fno-exceptions -DEIGEN_DONT_VECTORIZE -DBTL_PREFIX=eigen3_novec")
btl_add_target_property(btl_eigen3_novec_matmat COMPILE_FLAGS "-fno-exceptions -DEIGEN_DONT_VECTORIZE -DBTL_PREFIX=eigen3_novec")
btl_add_target_property(btl_eigen3_novec_adv COMPILE_FLAGS "-fno-exceptions -DEIGEN_DONT_VECTORIZE -DBTL_PREFIX=eigen3_novec")
# if(BUILD_btl_eigen3_adv)
# target_link_libraries(btl_eigen3_adv ${MKL_LIBRARIES})
# endif()
endif()
btl_add_bench(btl_tiny_eigen3 btl_tiny_eigen3.cpp OFF)
if(NOT BTL_NOVEC)
btl_add_bench(btl_tiny_eigen3_novec btl_tiny_eigen3.cpp OFF)
btl_add_target_property(btl_tiny_eigen3_novec COMPILE_FLAGS "-DBTL_PREFIX=eigen3_tiny")
if(BUILD_btl_tiny_eigen3_novec)
btl_add_target_property(btl_tiny_eigen3_novec COMPILE_FLAGS "-DEIGEN_DONT_VECTORIZE -DBTL_PREFIX=eigen3_tiny_novec")
endif()
endif()
endif ()
@@ -0,0 +1,46 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen3_interface.hh"
#include "static/bench_static.hh"
#include "action_matrix_vector_product.hh"
#include "action_matrix_matrix_product.hh"
#include "action_axpy.hh"
#include "action_lu_solve.hh"
#include "action_ata_product.hh"
#include "action_aat_product.hh"
#include "action_atv_product.hh"
#include "action_cholesky.hh"
#include "action_trisolve.hh"
BTL_MAIN;
int main()
{
bench_static<Action_axpy,eigen2_interface>();
bench_static<Action_matrix_matrix_product,eigen2_interface>();
bench_static<Action_matrix_vector_product,eigen2_interface>();
bench_static<Action_atv_product,eigen2_interface>();
bench_static<Action_cholesky,eigen2_interface>();
bench_static<Action_trisolve,eigen2_interface>();
return 0;
}
@@ -0,0 +1,44 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen3_interface.hh"
#include "bench.hh"
#include "action_trisolve.hh"
#include "action_trisolve_matrix.hh"
#include "action_cholesky.hh"
#include "action_hessenberg.hh"
#include "action_lu_decomp.hh"
#include "action_partial_lu.hh"
BTL_MAIN;
int main()
{
bench<Action_trisolve<eigen3_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
bench<Action_trisolve_matrix<eigen3_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
bench<Action_cholesky<eigen3_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
// bench<Action_lu_decomp<eigen3_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
bench<Action_partial_lu<eigen3_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
// bench<Action_hessenberg<eigen3_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
bench<Action_tridiagonalization<eigen3_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
return 0;
}
@@ -0,0 +1,35 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen3_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_axpy<eigen3_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<eigen3_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_rot<eigen3_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
return 0;
}
@@ -0,0 +1,35 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen3_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_matrix_matrix_product<eigen3_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_ata_product<eigen3_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_aat_product<eigen3_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_trmm<eigen3_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,36 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "eigen3_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_matrix_vector_product<eigen3_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<eigen3_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_symv<eigen3_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_syr2<eigen3_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_ger<eigen3_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
return 0;
}
@@ -0,0 +1,6 @@
find_package(GMM)
if (GMM_FOUND)
include_directories(${GMM_INCLUDES})
btl_add_bench(btl_gmm main.cpp)
endif ()
@@ -0,0 +1,51 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "gmm_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
#include "action_hessenberg.hh"
#include "action_partial_lu.hh"
BTL_MAIN;
int main()
{
bench<Action_axpy<gmm_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<gmm_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_matrix_vector_product<gmm_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<gmm_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_matrix_matrix_product<gmm_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_ata_product<gmm_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_aat_product<gmm_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_trisolve<gmm_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
//bench<Action_lu_solve<blitz_LU_solve_interface<REAL_TYPE> > >(MIN_LU,MAX_LU,NB_POINT);
bench<Action_partial_lu<gmm_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_hessenberg<gmm_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_tridiagonalization<gmm_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,6 @@
find_package(MTL4)
if (MTL4_FOUND)
include_directories(${MTL4_INCLUDE_DIR})
btl_add_bench(btl_mtl4 main.cpp)
endif ()
@@ -0,0 +1,46 @@
//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "mtl4_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
#include "action_cholesky.hh"
// #include "action_lu_decomp.hh"
BTL_MAIN;
int main()
{
bench<Action_axpy<mtl4_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<mtl4_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_matrix_vector_product<mtl4_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<mtl4_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_matrix_matrix_product<mtl4_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_ata_product<mtl4_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_aat_product<mtl4_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_trisolve<mtl4_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_cholesky<mtl4_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_lu_decomp<mtl4_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,44 @@
if((NOT TENSOR_INCLUDE_DIR) AND Eigen_SOURCE_DIR)
# unless TENSOR_INCLUDE_DIR is defined, let's use current Eigen version
set(TENSOR_INCLUDE_DIR ${Eigen_SOURCE_DIR})
set(TENSOR_FOUND TRUE)
else()
find_package(Tensor)
endif()
if (TENSOR_FOUND)
include_directories(${TENSOR_INCLUDE_DIR})
btl_add_bench(btl_tensor_linear main_linear.cpp)
btl_add_bench(btl_tensor_vecmat main_vecmat.cpp)
btl_add_bench(btl_tensor_matmat main_matmat.cpp)
btl_add_target_property(btl_tensor_linear COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=tensor")
btl_add_target_property(btl_tensor_vecmat COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=tensor")
btl_add_target_property(btl_tensor_matmat COMPILE_FLAGS "-fno-exceptions -DBTL_PREFIX=tensor")
option(BTL_BENCH_NOGCCVEC "also bench Eigen explicit vec without GCC's auto vec" OFF)
if(CMAKE_COMPILER_IS_GNUCXX AND BTL_BENCH_NOGCCVEC)
btl_add_bench(btl_tensor_nogccvec_linear main_linear.cpp)
btl_add_bench(btl_tensor_nogccvec_vecmat main_vecmat.cpp)
btl_add_bench(btl_tensor_nogccvec_matmat main_matmat.cpp)
btl_add_target_property(btl_tensor_nogccvec_linear COMPILE_FLAGS "-fno-exceptions -fno-tree-vectorize -DBTL_PREFIX=tensor_nogccvec")
btl_add_target_property(btl_tensor_nogccvec_vecmat COMPILE_FLAGS "-fno-exceptions -fno-tree-vectorize -DBTL_PREFIX=tensor_nogccvec")
btl_add_target_property(btl_tensor_nogccvec_matmat COMPILE_FLAGS "-fno-exceptions -fno-tree-vectorize -DBTL_PREFIX=tensor_nogccvec")
endif()
if(NOT BTL_NOVEC)
btl_add_bench(btl_tensor_novec_linear main_linear.cpp OFF)
btl_add_bench(btl_tensor_novec_vecmat main_vecmat.cpp OFF)
btl_add_bench(btl_tensor_novec_matmat main_matmat.cpp OFF)
btl_add_target_property(btl_tensor_novec_linear COMPILE_FLAGS "-fno-exceptions -DEIGEN_DONT_VECTORIZE -DBTL_PREFIX=tensor_novec")
btl_add_target_property(btl_tensor_novec_vecmat COMPILE_FLAGS "-fno-exceptions -DEIGEN_DONT_VECTORIZE -DBTL_PREFIX=tensor_novec")
btl_add_target_property(btl_tensor_novec_matmat COMPILE_FLAGS "-fno-exceptions -DEIGEN_DONT_VECTORIZE -DBTL_PREFIX=tensor_novec")
endif()
endif ()
@@ -0,0 +1,23 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "utilities.h"
#include "tensor_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_axpy<tensor_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<tensor_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
return 0;
}
@@ -0,0 +1,21 @@
//=====================================================
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//=====================================================
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
#include "utilities.h"
#include "tensor_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_matrix_matrix_product<tensor_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,21 @@
//=====================================================
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//=====================================================
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
#include "utilities.h"
#include "tensor_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_matrix_vector_product<tensor_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
return 0;
}
@@ -0,0 +1,6 @@
find_package(Tvmet)
if (TVMET_FOUND)
include_directories(${TVMET_INCLUDE_DIR})
btl_add_bench(btl_tvmet main.cpp OFF)
endif ()
@@ -0,0 +1,40 @@
//=====================================================
// File : main.cpp
// Author : L. Plagne <laurent.plagne@edf.fr)>
// Copyright (C) EDF R&D, lun sep 30 14:23:30 CEST 2002
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "tvmet_interface.hh"
#include "static/bench_static.hh"
#include "action_matrix_vector_product.hh"
#include "action_matrix_matrix_product.hh"
#include "action_atv_product.hh"
#include "action_axpy.hh"
BTL_MAIN;
int main()
{
bench_static<Action_axpy,tvmet_interface>();
bench_static<Action_matrix_matrix_product,tvmet_interface>();
bench_static<Action_matrix_vector_product,tvmet_interface>();
bench_static<Action_atv_product,tvmet_interface>();
return 0;
}
@@ -0,0 +1,7 @@
find_package(Boost)
if (Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${Boost_INCLUDES})
btl_add_bench(btl_ublas main.cpp)
endif ()
@@ -0,0 +1,44 @@
//=====================================================
// File : main.cpp
// Author : L. Plagne <laurent.plagne@edf.fr)>
// Copyright (C) EDF R&D, lun sep 30 14:23:27 CEST 2002
//=====================================================
//
// 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.
//
#include "utilities.h"
#include "ublas_interface.hh"
#include "bench.hh"
#include "basic_actions.hh"
BTL_MAIN;
int main()
{
bench<Action_axpy<ublas_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_axpby<ublas_interface<REAL_TYPE> > >(MIN_AXPY,MAX_AXPY,NB_POINT);
bench<Action_matrix_vector_product<ublas_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_atv_product<ublas_interface<REAL_TYPE> > >(MIN_MV,MAX_MV,NB_POINT);
bench<Action_matrix_matrix_product<ublas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_ata_product<ublas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
// bench<Action_aat_product<ublas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
bench<Action_trisolve<ublas_interface<REAL_TYPE> > >(MIN_MM,MAX_MM,NB_POINT);
return 0;
}
@@ -0,0 +1,101 @@
#define EIGEN_INTERNAL_DEBUG_CACHE_QUERY
#include <iostream>
#include "../Eigen/Core"
using namespace Eigen;
using namespace std;
#define DUMP_CPUID(CODE) {\
int abcd[4]; \
abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;\
EIGEN_CPUID(abcd, CODE, 0); \
std::cout << "The code " << CODE << " gives " \
<< (int*)(abcd[0]) << " " << (int*)(abcd[1]) << " " \
<< (int*)(abcd[2]) << " " << (int*)(abcd[3]) << " " << std::endl; \
}
int main()
{
cout << "Eigen's L1 = " << internal::queryL1CacheSize() << endl;
cout << "Eigen's L2/L3 = " << internal::queryTopLevelCacheSize() << endl;
int l1, l2, l3;
internal::queryCacheSizes(l1, l2, l3);
cout << "Eigen's L1, L2, L3 = " << l1 << " " << l2 << " " << l3 << endl;
#ifdef EIGEN_CPUID
int abcd[4];
int string[8];
char* string_char = (char*)(string);
// vendor ID
EIGEN_CPUID(abcd,0x0,0);
string[0] = abcd[1];
string[1] = abcd[3];
string[2] = abcd[2];
string[3] = 0;
cout << endl;
cout << "vendor id = " << string_char << endl;
cout << endl;
int max_funcs = abcd[0];
internal::queryCacheSizes_intel_codes(l1, l2, l3);
cout << "Eigen's intel codes L1, L2, L3 = " << l1 << " " << l2 << " " << l3 << endl;
if(max_funcs>=4)
{
internal::queryCacheSizes_intel_direct(l1, l2, l3);
cout << "Eigen's intel direct L1, L2, L3 = " << l1 << " " << l2 << " " << l3 << endl;
}
internal::queryCacheSizes_amd(l1, l2, l3);
cout << "Eigen's amd L1, L2, L3 = " << l1 << " " << l2 << " " << l3 << endl;
cout << endl;
// dump Intel direct method
if(max_funcs>=4)
{
l1 = l2 = l3 = 0;
int cache_id = 0;
int cache_type = 0;
do {
abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
EIGEN_CPUID(abcd,0x4,cache_id);
cache_type = (abcd[0] & 0x0F) >> 0;
int cache_level = (abcd[0] & 0xE0) >> 5; // A[7:5]
int ways = (abcd[1] & 0xFFC00000) >> 22; // B[31:22]
int partitions = (abcd[1] & 0x003FF000) >> 12; // B[21:12]
int line_size = (abcd[1] & 0x00000FFF) >> 0; // B[11:0]
int sets = (abcd[2]); // C[31:0]
int cache_size = (ways+1) * (partitions+1) * (line_size+1) * (sets+1);
cout << "cache[" << cache_id << "].type = " << cache_type << "\n";
cout << "cache[" << cache_id << "].level = " << cache_level << "\n";
cout << "cache[" << cache_id << "].ways = " << ways << "\n";
cout << "cache[" << cache_id << "].partitions = " << partitions << "\n";
cout << "cache[" << cache_id << "].line_size = " << line_size << "\n";
cout << "cache[" << cache_id << "].sets = " << sets << "\n";
cout << "cache[" << cache_id << "].size = " << cache_size << "\n";
cache_id++;
} while(cache_type>0 && cache_id<16);
}
// dump everything
std::cout << endl <<"Raw dump:" << endl;
for(int i=0; i<max_funcs; ++i)
DUMP_CPUID(i);
DUMP_CPUID(0x80000000);
DUMP_CPUID(0x80000001);
DUMP_CPUID(0x80000002);
DUMP_CPUID(0x80000003);
DUMP_CPUID(0x80000004);
DUMP_CPUID(0x80000005);
DUMP_CPUID(0x80000006);
DUMP_CPUID(0x80000007);
DUMP_CPUID(0x80000008);
#else
cout << "EIGEN_CPUID is not defined" << endl;
#endif
return 0;
}
@@ -0,0 +1,186 @@
#include <iostream>
#include "BenchTimer.h"
#include <Eigen/Dense>
#include <map>
#include <vector>
#include <string>
#include <sstream>
using namespace Eigen;
std::map<std::string,Array<float,1,8,DontAlign|RowMajor> > results;
std::vector<std::string> labels;
std::vector<Array2i> sizes;
template<typename Solver,typename MatrixType>
EIGEN_DONT_INLINE
void compute_norm_equation(Solver &solver, const MatrixType &A) {
if(A.rows()!=A.cols())
solver.compute(A.transpose()*A);
else
solver.compute(A);
}
template<typename Solver,typename MatrixType>
EIGEN_DONT_INLINE
void compute(Solver &solver, const MatrixType &A) {
solver.compute(A);
}
template<typename Scalar,int Size>
void bench(int id, int rows, int size = Size)
{
typedef Matrix<Scalar,Dynamic,Size> Mat;
typedef Matrix<Scalar,Dynamic,Dynamic> MatDyn;
typedef Matrix<Scalar,Size,Size> MatSquare;
Mat A(rows,size);
A.setRandom();
if(rows==size)
A = A*A.adjoint();
BenchTimer t_llt, t_ldlt, t_lu, t_fplu, t_qr, t_cpqr, t_cod, t_fpqr, t_jsvd, t_bdcsvd;
int svd_opt = ComputeThinU|ComputeThinV;
int tries = 5;
int rep = 1000/size;
if(rep==0) rep = 1;
// rep = rep*rep;
LLT<MatSquare> llt(size);
LDLT<MatSquare> ldlt(size);
PartialPivLU<MatSquare> lu(size);
FullPivLU<MatSquare> fplu(size,size);
HouseholderQR<Mat> qr(A.rows(),A.cols());
ColPivHouseholderQR<Mat> cpqr(A.rows(),A.cols());
CompleteOrthogonalDecomposition<Mat> cod(A.rows(),A.cols());
FullPivHouseholderQR<Mat> fpqr(A.rows(),A.cols());
JacobiSVD<MatDyn> jsvd(A.rows(),A.cols());
BDCSVD<MatDyn> bdcsvd(A.rows(),A.cols());
BENCH(t_llt, tries, rep, compute_norm_equation(llt,A));
BENCH(t_ldlt, tries, rep, compute_norm_equation(ldlt,A));
BENCH(t_lu, tries, rep, compute_norm_equation(lu,A));
if(size<=1000)
BENCH(t_fplu, tries, rep, compute_norm_equation(fplu,A));
BENCH(t_qr, tries, rep, compute(qr,A));
BENCH(t_cpqr, tries, rep, compute(cpqr,A));
BENCH(t_cod, tries, rep, compute(cod,A));
if(size*rows<=10000000)
BENCH(t_fpqr, tries, rep, compute(fpqr,A));
if(size<500) // JacobiSVD is really too slow for too large matrices
BENCH(t_jsvd, tries, rep, jsvd.compute(A,svd_opt));
// if(size*rows<=20000000)
BENCH(t_bdcsvd, tries, rep, bdcsvd.compute(A,svd_opt));
results["LLT"][id] = t_llt.best();
results["LDLT"][id] = t_ldlt.best();
results["PartialPivLU"][id] = t_lu.best();
results["FullPivLU"][id] = t_fplu.best();
results["HouseholderQR"][id] = t_qr.best();
results["ColPivHouseholderQR"][id] = t_cpqr.best();
results["CompleteOrthogonalDecomposition"][id] = t_cod.best();
results["FullPivHouseholderQR"][id] = t_fpqr.best();
results["JacobiSVD"][id] = t_jsvd.best();
results["BDCSVD"][id] = t_bdcsvd.best();
}
int main()
{
labels.push_back("LLT");
labels.push_back("LDLT");
labels.push_back("PartialPivLU");
labels.push_back("FullPivLU");
labels.push_back("HouseholderQR");
labels.push_back("ColPivHouseholderQR");
labels.push_back("CompleteOrthogonalDecomposition");
labels.push_back("FullPivHouseholderQR");
labels.push_back("JacobiSVD");
labels.push_back("BDCSVD");
for(int i=0; i<labels.size(); ++i)
results[labels[i]].fill(-1);
const int small = 8;
sizes.push_back(Array2i(small,small));
sizes.push_back(Array2i(100,100));
sizes.push_back(Array2i(1000,1000));
sizes.push_back(Array2i(4000,4000));
sizes.push_back(Array2i(10000,small));
sizes.push_back(Array2i(10000,100));
sizes.push_back(Array2i(10000,1000));
sizes.push_back(Array2i(10000,4000));
using namespace std;
for(int k=0; k<sizes.size(); ++k)
{
cout << sizes[k](0) << "x" << sizes[k](1) << "...\n";
bench<float,Dynamic>(k,sizes[k](0),sizes[k](1));
}
cout.width(32);
cout << "solver/size";
cout << " ";
for(int k=0; k<sizes.size(); ++k)
{
std::stringstream ss;
ss << sizes[k](0) << "x" << sizes[k](1);
cout.width(10); cout << ss.str(); cout << " ";
}
cout << endl;
for(int i=0; i<labels.size(); ++i)
{
cout.width(32); cout << labels[i]; cout << " ";
ArrayXf r = (results[labels[i]]*100000.f).floor()/100.f;
for(int k=0; k<sizes.size(); ++k)
{
cout.width(10);
if(r(k)>=1e6) cout << "-";
else cout << r(k);
cout << " ";
}
cout << endl;
}
// HTML output
cout << "<table class=\"manual\">" << endl;
cout << "<tr><th>solver/size</th>" << endl;
for(int k=0; k<sizes.size(); ++k)
cout << " <th>" << sizes[k](0) << "x" << sizes[k](1) << "</th>";
cout << "</tr>" << endl;
for(int i=0; i<labels.size(); ++i)
{
cout << "<tr";
if(i%2==1) cout << " class=\"alt\"";
cout << "><td>" << labels[i] << "</td>";
ArrayXf r = (results[labels[i]]*100000.f).floor()/100.f;
for(int k=0; k<sizes.size(); ++k)
{
if(r(k)>=1e6) cout << "<td>-</td>";
else
{
cout << "<td>" << r(k);
if(i>0)
cout << " (x" << numext::round(10.f*results[labels[i]](k)/results["LLT"](k))/10.f << ")";
if(i<4 && sizes[k](0)!=sizes[k](1))
cout << " <sup><a href=\"#note_ls\">*</a></sup>";
cout << "</td>";
}
}
cout << "</tr>" << endl;
}
cout << "</table>" << endl;
// cout << "LLT (ms) " << (results["LLT"]*1000.).format(fmt) << "\n";
// cout << "LDLT (%) " << (results["LDLT"]/results["LLT"]).format(fmt) << "\n";
// cout << "PartialPivLU (%) " << (results["PartialPivLU"]/results["LLT"]).format(fmt) << "\n";
// cout << "FullPivLU (%) " << (results["FullPivLU"]/results["LLT"]).format(fmt) << "\n";
// cout << "HouseholderQR (%) " << (results["HouseholderQR"]/results["LLT"]).format(fmt) << "\n";
// cout << "ColPivHouseholderQR (%) " << (results["ColPivHouseholderQR"]/results["LLT"]).format(fmt) << "\n";
// cout << "CompleteOrthogonalDecomposition (%) " << (results["CompleteOrthogonalDecomposition"]/results["LLT"]).format(fmt) << "\n";
// cout << "FullPivHouseholderQR (%) " << (results["FullPivHouseholderQR"]/results["LLT"]).format(fmt) << "\n";
// cout << "JacobiSVD (%) " << (results["JacobiSVD"]/results["LLT"]).format(fmt) << "\n";
// cout << "BDCSVD (%) " << (results["BDCSVD"]/results["LLT"]).format(fmt) << "\n";
}
@@ -0,0 +1,195 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// The computeRoots function included in this is based on materials
// covered by the following copyright and license:
//
// Geometric Tools, LLC
// Copyright (c) 1998-2010
// Distributed under the Boost Software License, Version 1.0.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>
using namespace Eigen;
using namespace std;
template<typename Matrix, typename Roots>
inline void computeRoots(const Matrix& m, Roots& roots)
{
typedef typename Matrix::Scalar Scalar;
const Scalar s_inv3 = 1.0/3.0;
const Scalar s_sqrt3 = std::sqrt(Scalar(3.0));
// The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The
// eigenvalues are the roots to this equation, all guaranteed to be
// real-valued, because the matrix is symmetric.
Scalar c0 = m(0,0)*m(1,1)*m(2,2) + Scalar(2)*m(0,1)*m(0,2)*m(1,2) - m(0,0)*m(1,2)*m(1,2) - m(1,1)*m(0,2)*m(0,2) - m(2,2)*m(0,1)*m(0,1);
Scalar c1 = m(0,0)*m(1,1) - m(0,1)*m(0,1) + m(0,0)*m(2,2) - m(0,2)*m(0,2) + m(1,1)*m(2,2) - m(1,2)*m(1,2);
Scalar c2 = m(0,0) + m(1,1) + m(2,2);
// Construct the parameters used in classifying the roots of the equation
// and in solving the equation for the roots in closed form.
Scalar c2_over_3 = c2*s_inv3;
Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3;
if (a_over_3 > Scalar(0))
a_over_3 = Scalar(0);
Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));
Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3;
if (q > Scalar(0))
q = Scalar(0);
// Compute the eigenvalues by solving for the roots of the polynomial.
Scalar rho = std::sqrt(-a_over_3);
Scalar theta = std::atan2(std::sqrt(-q),half_b)*s_inv3;
Scalar cos_theta = std::cos(theta);
Scalar sin_theta = std::sin(theta);
roots(2) = c2_over_3 + Scalar(2)*rho*cos_theta;
roots(0) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta);
roots(1) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta);
}
template<typename Matrix, typename Vector>
void eigen33(const Matrix& mat, Matrix& evecs, Vector& evals)
{
typedef typename Matrix::Scalar Scalar;
// Scale the matrix so its entries are in [-1,1]. The scaling is applied
// only when at least one matrix entry has magnitude larger than 1.
Scalar shift = mat.trace()/3;
Matrix scaledMat = mat;
scaledMat.diagonal().array() -= shift;
Scalar scale = scaledMat.cwiseAbs()/*.template triangularView<Lower>()*/.maxCoeff();
scale = std::max(scale,Scalar(1));
scaledMat/=scale;
// Compute the eigenvalues
// scaledMat.setZero();
computeRoots(scaledMat,evals);
// compute the eigen vectors
// **here we assume 3 different eigenvalues**
// "optimized version" which appears to be slower with gcc!
// Vector base;
// Scalar alpha, beta;
// base << scaledMat(1,0) * scaledMat(2,1),
// scaledMat(1,0) * scaledMat(2,0),
// -scaledMat(1,0) * scaledMat(1,0);
// for(int k=0; k<2; ++k)
// {
// alpha = scaledMat(0,0) - evals(k);
// beta = scaledMat(1,1) - evals(k);
// evecs.col(k) = (base + Vector(-beta*scaledMat(2,0), -alpha*scaledMat(2,1), alpha*beta)).normalized();
// }
// evecs.col(2) = evecs.col(0).cross(evecs.col(1)).normalized();
// // naive version
// Matrix tmp;
// tmp = scaledMat;
// tmp.diagonal().array() -= evals(0);
// evecs.col(0) = tmp.row(0).cross(tmp.row(1)).normalized();
//
// tmp = scaledMat;
// tmp.diagonal().array() -= evals(1);
// evecs.col(1) = tmp.row(0).cross(tmp.row(1)).normalized();
//
// tmp = scaledMat;
// tmp.diagonal().array() -= evals(2);
// evecs.col(2) = tmp.row(0).cross(tmp.row(1)).normalized();
// a more stable version:
if((evals(2)-evals(0))<=Eigen::NumTraits<Scalar>::epsilon())
{
evecs.setIdentity();
}
else
{
Matrix tmp;
tmp = scaledMat;
tmp.diagonal ().array () -= evals (2);
evecs.col (2) = tmp.row (0).cross (tmp.row (1)).normalized ();
tmp = scaledMat;
tmp.diagonal ().array () -= evals (1);
evecs.col(1) = tmp.row (0).cross(tmp.row (1));
Scalar n1 = evecs.col(1).norm();
if(n1<=Eigen::NumTraits<Scalar>::epsilon())
evecs.col(1) = evecs.col(2).unitOrthogonal();
else
evecs.col(1) /= n1;
// make sure that evecs[1] is orthogonal to evecs[2]
evecs.col(1) = evecs.col(2).cross(evecs.col(1).cross(evecs.col(2))).normalized();
evecs.col(0) = evecs.col(2).cross(evecs.col(1));
}
// Rescale back to the original size.
evals *= scale;
evals.array()+=shift;
}
int main()
{
BenchTimer t;
int tries = 10;
int rep = 400000;
typedef Matrix3d Mat;
typedef Vector3d Vec;
Mat A = Mat::Random(3,3);
A = A.adjoint() * A;
// Mat Q = A.householderQr().householderQ();
// A = Q * Vec(2.2424567,2.2424566,7.454353).asDiagonal() * Q.transpose();
SelfAdjointEigenSolver<Mat> eig(A);
BENCH(t, tries, rep, eig.compute(A));
std::cout << "Eigen iterative: " << t.best() << "s\n";
BENCH(t, tries, rep, eig.computeDirect(A));
std::cout << "Eigen direct : " << t.best() << "s\n";
Mat evecs;
Vec evals;
BENCH(t, tries, rep, eigen33(A,evecs,evals));
std::cout << "Direct: " << t.best() << "s\n\n";
// std::cerr << "Eigenvalue/eigenvector diffs:\n";
// std::cerr << (evals - eig.eigenvalues()).transpose() << "\n";
// for(int k=0;k<3;++k)
// if(evecs.col(k).dot(eig.eigenvectors().col(k))<0)
// evecs.col(k) = -evecs.col(k);
// std::cerr << evecs - eig.eigenvectors() << "\n\n";
}
@@ -0,0 +1,126 @@
#include <iostream>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>
using namespace std;
using namespace Eigen;
#ifndef SCALAR
#define SCALAR float
#endif
#ifndef SIZE
#define SIZE 8
#endif
typedef SCALAR Scalar;
typedef NumTraits<Scalar>::Real RealScalar;
typedef Matrix<RealScalar,Dynamic,Dynamic> A;
typedef Matrix</*Real*/Scalar,Dynamic,Dynamic> B;
typedef Matrix<Scalar,Dynamic,Dynamic> C;
typedef Matrix<RealScalar,Dynamic,Dynamic> M;
template<typename Transformation, typename Data>
EIGEN_DONT_INLINE void transform(const Transformation& t, Data& data)
{
EIGEN_ASM_COMMENT("begin");
data = t * data;
EIGEN_ASM_COMMENT("end");
}
template<typename Scalar, typename Data>
EIGEN_DONT_INLINE void transform(const Quaternion<Scalar>& t, Data& data)
{
EIGEN_ASM_COMMENT("begin quat");
for(int i=0;i<data.cols();++i)
data.col(i) = t * data.col(i);
EIGEN_ASM_COMMENT("end quat");
}
template<typename T> struct ToRotationMatrixWrapper
{
enum {Dim = T::Dim};
typedef typename T::Scalar Scalar;
ToRotationMatrixWrapper(const T& o) : object(o) {}
T object;
};
template<typename QType, typename Data>
EIGEN_DONT_INLINE void transform(const ToRotationMatrixWrapper<QType>& t, Data& data)
{
EIGEN_ASM_COMMENT("begin quat via mat");
data = t.object.toRotationMatrix() * data;
EIGEN_ASM_COMMENT("end quat via mat");
}
template<typename Scalar, int Dim, typename Data>
EIGEN_DONT_INLINE void transform(const Transform<Scalar,Dim,Projective>& t, Data& data)
{
data = (t * data.colwise().homogeneous()).template block<Dim,Data::ColsAtCompileTime>(0,0);
}
template<typename T> struct get_dim { enum { Dim = T::Dim }; };
template<typename S, int R, int C, int O, int MR, int MC>
struct get_dim<Matrix<S,R,C,O,MR,MC> > { enum { Dim = R }; };
template<typename Transformation, int N>
struct bench_impl
{
static EIGEN_DONT_INLINE void run(const Transformation& t)
{
Matrix<typename Transformation::Scalar,get_dim<Transformation>::Dim,N> data;
data.setRandom();
bench_impl<Transformation,N-1>::run(t);
BenchTimer timer;
BENCH(timer,10,100000,transform(t,data));
cout.width(9);
cout << timer.best() << " ";
}
};
template<typename Transformation>
struct bench_impl<Transformation,0>
{
static EIGEN_DONT_INLINE void run(const Transformation&) {}
};
template<typename Transformation>
EIGEN_DONT_INLINE void bench(const std::string& msg, const Transformation& t)
{
cout << msg << " ";
bench_impl<Transformation,SIZE>::run(t);
std::cout << "\n";
}
int main(int argc, char ** argv)
{
Matrix<Scalar,3,4> mat34; mat34.setRandom();
Transform<Scalar,3,Isometry> iso3(mat34);
Transform<Scalar,3,Affine> aff3(mat34);
Transform<Scalar,3,AffineCompact> caff3(mat34);
Transform<Scalar,3,Projective> proj3(mat34);
Quaternion<Scalar> quat;quat.setIdentity();
ToRotationMatrixWrapper<Quaternion<Scalar> > quatmat(quat);
Matrix<Scalar,3,3> mat33; mat33.setRandom();
cout.precision(4);
std::cout
<< "N ";
for(int i=0;i<SIZE;++i)
{
cout.width(9);
cout << i+1 << " ";
}
cout << "\n";
bench("matrix 3x3", mat33);
bench("quaternion", quat);
bench("quat-mat ", quatmat);
bench("isometry3 ", iso3);
bench("affine3 ", aff3);
bench("c affine3 ", caff3);
bench("proj3 ", proj3);
}
@@ -0,0 +1,95 @@
Load hg-to-git hash maps from ./eigen_git/.git/
#3.0.1
#3.1.1
#3.2.0
3.2.4
#574a7621809fe
58964a85800bd # introduce AVX
#589cbd7e98174 # merge
589db7d49efbb # introduce FMA
#590a078f442a3 # complex and AVX
590a419cea4a0 # improve packing with ptranspose
#59251e85c936d # merge
#592e497a27ddc
593d5a795f673 # New gebp kernel: up to 3 packets x 4 register-level blocks
#5942c3c95990d # merge
#596c9788d55b9 # Disable 3pX4 kernel on Altivec
#5999aa3dc4e21 # merge
6209452eb38f8 # before-evaluators
#6333eba5e1101 # Implement evaluator for sparse outer products
#663b9d314ae19
#6655ef95fabee # Properly detect FMA support on ARM
#667fe25f3b8e3 # FMA has been wrongly disabled
#668409547a0c8
#6694304c73542 # merge default to tensors
#67216047c8d4a # merge default to tensors
#67410a79ca3a3 # merge default to tensors
#674b7271dffb5 # Generalized the gebp apis
676bfdd9f3ac9 # Made the blocking computation aware of the l3 cache;<br/> Also optimized the blocking parameters to take<br/> into account the number of threads used for a computation.
6782dde63499c # generalized gemv
6799f98650d0a # ensured that contractions that can be reduced to a matrix vector product
#6840918c51e60 # merge tensor
684e972b55ec4 # change prefetching in gebp
#68598604576d1 # merge index conversion
68963eb0f6fe6 # clean blocking size computation
689db05f2d01e # rotating kernel for ARM only
#6901b7e12847d # result_of
69226275b250a # fix prefetching change for ARM
692692136350b # prefetching
693a8ad8887bf # blocking size strategy
693bcf9bb5c1f # avoid redundant pack_rhs
6987550107028 # dynamic loop swapping
69858740ce4c6 # rm dynamic loop swapping,<br/> adjust lhs's micro panel height to fully exploit L1 cache
698cd3bbffa73 # blocking heuristic:<br/> block on the rhs in L1 if the lhs fit in L1.
701488c15615a # organize a little our default cache sizes,<br/> and use a saner default L1 outside of x86 (10% faster on Nexus 5)
701e56aabf205 # Refactor computeProductBlockingSizes to make room<br/> for the possibility of using lookup tables
701ca5c12587b # Polish lookup tables generation
7013589a9c115 # actual_panel_rows computation should always be resilient<br/> to parameters not consistent with the known L1 cache size, see comment
70102babb9c0f # Provide a empirical lookup table for blocking sizes measured on a Nexus 5.<br/> Only for float, only for Android on ARM 32bit for now.
7088481dc21ea # Bug 986: add support for coefficient-based<br/> product with 0 depth.
709d7f51feb07 # Bug 992: don't select a 3p GEMM path with non-SIMD scalar types.
759f9303cc7c5 # 3.3-alpha1
765aba1eda71e # help clang inlining
770fe630c9873 # Improve numerical accuracy in LLT and triangular solve<br/> by using true scalar divisions (instead of x * (1/y))
#8741d23430628 # Improved the matrix multiplication blocking in the case<br/> where mr is not a power of 2 (e.g on Haswell CPUs)
878f629fe95c8 # Made the index type a template parameter to evaluateProductBlockingSizes.<br/> Use numext::mini and numext::maxi instead of <br/> std::min/std::max to compute blocking sizes.
8975d51a7f12c # Don't optimize the processing of the last rows of<br/> a matrix matrix product in cases that violate<br/> the assumptions made by the optimized code path.
8986136f4fdd4 # Remove the rotating kernel.
898e68e165a23 # Bug 256: enable vectorization with unaligned loads/stores.
91466e99ab6a1 # Relax mixing-type constraints for binary coeff-wise operators
91776236cdea4 # merge
917101ea26f5e # Include the cost of stores in unrolling
921672076db5d # Fix perf regression introduced in changeset e56aabf205
9210fa9e4a15c # Fix perf regression in dgemm introduced by changeset 5d51a7f12c
936f6b3cf8de9 # 3.3-beta2
944504a4404f1 # Optimize expression matching 'd?=a-b*c' as 'd?=a; d?=b*c;'
95877e27fbeee # 3.3-rc1
959779774f98c # Bug 1311: fix alignment logic in some cases<br/> of (scalar*small).lazyProduct(small)
9729f9d8d2f62 # Disabled part of the matrix matrix peeling code<br/> that's incompatible with 512 bit registers
979eeac81b8c0 # 3.3.0
989c927af60ed # Fix a performance regression in (mat*mat)*vec<br/> for which mat*mat was evaluated multiple times.
994fe696022ec # Operators += and -= do not resize!
99466f65ccc36 # Ease compiler generating clean and efficient code in mat*vec
9946a5fe86098 # Complete rewrite of column-major-matrix * vector product<br/> to deliver higher performance of modern CPU.
99591003f3b86 # Improve performance of row-major-dense-matrix * vector products<br/> for recent CPUs.
997eb621413c1 # Revert vec/y to vec*(1/y) in row-major TRSM
10444bbc320468 # Bug 1435: fix aliasing issue in exressions like: A = C - B*A;
1073624df50945 # Adds missing EIGEN_STRONG_INLINE to support MSVC<br/> properly inlining small vector calculations
1094d428a199ab # Bug 1562: optimize evaluation of small products<br/> of the form s*A*B by rewriting them as: s*(A.lazyProduct(B))<br/> to save a costly temporary.<br/> Measured speedup from 2x to 5x.
1096de9e31a06d # Introduce the macro ei_declare_local_nested_eval to<br/> help allocating on the stack local temporaries via alloca,<br/> and let outer-products makes a good use of it.
11087b91c11207 # Bug 1578: Improve prefetching in matrix multiplication on MIPS.
1153aa110e681b # PR 526: Speed up multiplication of small, dynamically sized matrices
11544ad359237a # Vectorize row-by-row gebp loop iterations on 16 packets as well
1157a476054879 # Bug 1624: improve matrix-matrix product on ARM 64, 20% speedup
1160a4159dba08 # do not read buffers out of bounds
1163c53eececb0 # Implement AVX512 vectorization of std::complex<float/double>
11644e7746fe22 # Bug 1636: fix gemm performance issue with gcc>=6 and no FMA
1164956678a4ef # Bug 1515: disable gebp's 3pX4 micro kernel<br/> for MSVC<=19.14 because of register spilling.
1165426bce7529 # fix EIGEN_GEBP_2PX4_SPILLING_WORKAROUND<br/> for non vectorized type, and non x86/64 target
11660d90637838 # enable spilling workaround on architectures with SSE/AVX
1166f159cf3d75 # Artificially increase l1-blocking size for AVX512.<br/> +10% speedup with current kernels.
11686dd93f7e3b # Make code compile again for older compilers.
1175dbfcceabf5 # Bug: 1633: refactor gebp kernel and optimize for neon
117670e133333d # Bug 1661: fix regression in GEBP and AVX512
11760f028f61cb # GEBP: cleanup logic to choose between<br/> a 4 packets of 1 packet (=e118ce86fd+fix)
1180de77bf5d6c # gebp: Add new ½ and ¼ packet rows per (peeling) round on the lhs
@@ -0,0 +1,12 @@
#include "gemm_common.h"
EIGEN_DONT_INLINE
void gemm(const Mat &A, const Mat &B, Mat &C)
{
C.noalias() += A * B;
}
int main(int argc, char **argv)
{
return main_gemm(argc, argv, gemm);
}
@@ -0,0 +1,67 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include "eigen_src/Eigen/Core"
#include "../BenchTimer.h"
using namespace Eigen;
#ifndef SCALAR
#error SCALAR must be defined
#endif
typedef SCALAR Scalar;
typedef Matrix<Scalar,Dynamic,Dynamic> Mat;
template<typename Func>
EIGEN_DONT_INLINE
double bench(long m, long n, long k, const Func& f)
{
Mat A(m,k);
Mat B(k,n);
Mat C(m,n);
A.setRandom();
B.setRandom();
C.setZero();
BenchTimer t;
double up = 1e8*4/sizeof(Scalar);
double tm0 = 4, tm1 = 10;
if(NumTraits<Scalar>::IsComplex)
{
up /= 4;
tm0 = 2;
tm1 = 4;
}
double flops = 2. * m * n * k;
long rep = std::max(1., std::min(100., up/flops) );
long tries = std::max(tm0, std::min(tm1, up/flops) );
BENCH(t, tries, rep, f(A,B,C));
return 1e-9 * rep * flops / t.best();
}
template<typename Func>
int main_gemm(int argc, char **argv, const Func& f)
{
std::vector<double> results;
std::string filename = std::string("gemm_settings.txt");
if(argc>1)
filename = std::string(argv[1]);
std::ifstream settings(filename);
long m, n, k;
while(settings >> m >> n >> k)
{
//std::cerr << " Testing " << m << " " << n << " " << k << std::endl;
results.push_back( bench(m, n, k, f) );
}
std::cout << RowVectorXd::Map(results.data(), results.size());
return 0;
}
@@ -0,0 +1,15 @@
8 8 8
9 9 9
24 24 24
239 239 239
240 240 240
2400 24 24
24 2400 24
24 24 2400
24 2400 2400
2400 24 2400
2400 2400 24
2400 2400 64
4800 23 160
23 4800 160
2400 2400 2400
@@ -0,0 +1,11 @@
8 8 8
9 9 9
12 12 12
15 15 15
16 16 16
24 24 24
102 102 102
239 239 239
240 240 240
2400 2400 2400
2463 2463 2463
@@ -0,0 +1,12 @@
#include "gemv_common.h"
EIGEN_DONT_INLINE
void gemv(const Mat &A, const Vec &B, Vec &C)
{
C.noalias() += A * B;
}
int main(int argc, char **argv)
{
return main_gemv(argc, argv, gemv);
}
@@ -0,0 +1,69 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <functional>
#include "eigen_src/Eigen/Core"
#include "../BenchTimer.h"
using namespace Eigen;
#ifndef SCALAR
#error SCALAR must be defined
#endif
typedef SCALAR Scalar;
typedef Matrix<Scalar,Dynamic,Dynamic> Mat;
typedef Matrix<Scalar,Dynamic,1> Vec;
template<typename Func>
EIGEN_DONT_INLINE
double bench(long m, long n, Func &f)
{
Mat A(m,n);
Vec B(n);
Vec C(m);
A.setRandom();
B.setRandom();
C.setRandom();
BenchTimer t;
double up = 1e8/sizeof(Scalar);
double tm0 = 4, tm1 = 10;
if(NumTraits<Scalar>::IsComplex)
{
up /= 4;
tm0 = 2;
tm1 = 4;
}
double flops = 2. * m * n;
long rep = std::max(1., std::min(100., up/flops) );
long tries = std::max(tm0, std::min(tm1, up/flops) );
BENCH(t, tries, rep, f(A,B,C));
return 1e-9 * rep * flops / t.best();
}
template<typename Func>
int main_gemv(int argc, char **argv, Func& f)
{
std::vector<double> results;
std::string filename = std::string("gemv_settings.txt");
if(argc>1)
filename = std::string(argv[1]);
std::ifstream settings(filename);
long m, n;
while(settings >> m >> n)
{
//std::cerr << " Testing " << m << " " << n << std::endl;
results.push_back( bench(m, n, f) );
}
std::cout << RowVectorXd::Map(results.data(), results.size());
return 0;
}
@@ -0,0 +1,11 @@
8 8
9 9
24 24
239 239
240 240
2400 24
24 2400
24 240
2400 2400
4800 23
23 4800
@@ -0,0 +1,13 @@
8 8
9 9
12 12
15 15
16 16
24 24
53 53
74 74
102 102
239 239
240 240
2400 2400
2463 2463
@@ -0,0 +1,12 @@
#include "gemv_common.h"
EIGEN_DONT_INLINE
void gemv(const Mat &A, Vec &B, const Vec &C)
{
B.noalias() += A.transpose() * C;
}
int main(int argc, char **argv)
{
return main_gemv(argc, argv, gemv);
}
@@ -0,0 +1,101 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <Eigen/Core>
#include "../../BenchTimer.h"
using namespace Eigen;
#ifndef SCALAR
#error SCALAR must be defined
#endif
typedef SCALAR Scalar;
template<typename MatA, typename MatB, typename MatC>
EIGEN_DONT_INLINE
void lazy_gemm(const MatA &A, const MatB &B, MatC &C)
{
// escape((void*)A.data());
// escape((void*)B.data());
C.noalias() += A.lazyProduct(B);
// escape((void*)C.data());
}
template<int m, int n, int k, int TA>
EIGEN_DONT_INLINE
double bench()
{
typedef Matrix<Scalar,m,k,TA> MatA;
typedef Matrix<Scalar,k,n> MatB;
typedef Matrix<Scalar,m,n> MatC;
MatA A(m,k);
MatB B(k,n);
MatC C(m,n);
A.setRandom();
B.setRandom();
C.setZero();
BenchTimer t;
double up = 1e7*4/sizeof(Scalar);
double tm0 = 10, tm1 = 20;
double flops = 2. * m * n * k;
long rep = std::max(10., std::min(10000., up/flops) );
long tries = std::max(tm0, std::min(tm1, up/flops) );
BENCH(t, tries, rep, lazy_gemm(A,B,C));
return 1e-9 * rep * flops / t.best();
}
template<int m, int n, int k>
double bench_t(int t)
{
if(t)
return bench<m,n,k,RowMajor>();
else
return bench<m,n,k,0>();
}
EIGEN_DONT_INLINE
double bench_mnk(int m, int n, int k, int t)
{
int id = m*10000 + n*100 + k;
switch(id) {
case 10101 : return bench_t< 1, 1, 1>(t); break;
case 20202 : return bench_t< 2, 2, 2>(t); break;
case 30303 : return bench_t< 3, 3, 3>(t); break;
case 40404 : return bench_t< 4, 4, 4>(t); break;
case 50505 : return bench_t< 5, 5, 5>(t); break;
case 60606 : return bench_t< 6, 6, 6>(t); break;
case 70707 : return bench_t< 7, 7, 7>(t); break;
case 80808 : return bench_t< 8, 8, 8>(t); break;
case 90909 : return bench_t< 9, 9, 9>(t); break;
case 101010 : return bench_t<10,10,10>(t); break;
case 111111 : return bench_t<11,11,11>(t); break;
case 121212 : return bench_t<12,12,12>(t); break;
}
return 0;
}
int main(int argc, char **argv)
{
std::vector<double> results;
std::string filename = std::string("lazy_gemm_settings.txt");
if(argc>1)
filename = std::string(argv[1]);
std::ifstream settings(filename);
long m, n, k, t;
while(settings >> m >> n >> k >> t)
{
//std::cerr << " Testing " << m << " " << n << " " << k << std::endl;
results.push_back( bench_mnk(m, n, k, t) );
}
std::cout << RowVectorXd::Map(results.data(), results.size());
return 0;
}
@@ -0,0 +1,15 @@
1 1 1 0
2 2 2 0
3 3 3 0
4 4 4 0
4 4 4 1
5 5 5 0
6 6 6 0
7 7 7 0
7 7 7 1
8 8 8 0
9 9 9 0
10 10 10 0
11 11 11 0
12 12 12 0
12 12 12 1
@@ -0,0 +1,15 @@
#include "gemm_common.h"
#include <Eigen/Cholesky>
EIGEN_DONT_INLINE
void llt(const Mat &A, const Mat &B, Mat &C)
{
C = A;
C.diagonal().array() += 1000;
Eigen::internal::llt_inplace<Mat::Scalar, Lower>::blocked(C);
}
int main(int argc, char **argv)
{
return main_gemm(argc, argv, llt);
}
@@ -0,0 +1,112 @@
#!/bin/bash
# base name of the bench
# it reads $1.out
# and generates $1.pdf
WHAT=$1
bench=$2
settings_file=$3
header="rev "
while read line
do
if [ ! -z '$line' ]; then
header="$header \"$line\""
fi
done < $settings_file
echo $header > $WHAT.out.header
cat $WHAT.out >> $WHAT.out.header
echo "set title '$WHAT'" > $WHAT.gnuplot
echo "set key autotitle columnhead outside " >> $WHAT.gnuplot
echo "set xtics rotate 1" >> $WHAT.gnuplot
echo "set term pdf color rounded enhanced fontscale 0.35 size 7in,5in" >> $WHAT.gnuplot
echo set output "'"$WHAT.pdf"'" >> $WHAT.gnuplot
col=`cat $settings_file | wc -l`
echo "plot for [col=2:$col+1] '$WHAT.out.header' using 0:col:xticlabels(1) with lines" >> $WHAT.gnuplot
echo " " >> $WHAT.gnuplot
gnuplot -persist < $WHAT.gnuplot
# generate a png file (thumbnail)
convert -colors 256 -background white -density 300 -resize 300 -quality 0 $WHAT.pdf -background white -flatten $WHAT.png
# clean
rm $WHAT.out.header $WHAT.gnuplot
# generate html/svg graph
echo " " > $WHAT.html
cat resources/chart_header.html > $WHAT.html
echo 'var customSettings = {"TITLE":"","SUBTITLE":"","XLABEL":"","YLABEL":""};' >> $WHAT.html
# 'data' is an array of datasets (i.e. curves), each of which is an object of the form
# {
# key: <name of the curve>,
# color: <optional color of the curve>,
# values: [{
# r: <revision number>,
# v: <GFlops>
# }]
# }
echo 'var data = [' >> $WHAT.html
col=2
while read line
do
if [ ! -z '$line' ]; then
header="$header \"$line\""
echo '{"key":"'$line'","values":[' >> $WHAT.html
i=0
while read line2
do
if [ ! -z "$line2" ]; then
val=`echo $line2 | cut -s -f $col -d ' '`
if [ -n "$val" ]; then # skip build failures
echo '{"r":'$i',"v":'$val'},' >> $WHAT.html
fi
fi
((i++))
done < $WHAT.out
echo ']},' >> $WHAT.html
fi
((col++))
done < $settings_file
echo '];' >> $WHAT.html
echo 'var changesets = [' >> $WHAT.html
while read line2
do
if [ ! -z '$line2' ]; then
echo '"'`echo $line2 | cut -f 1 -d ' '`'",' >> $WHAT.html
fi
done < $WHAT.out
echo '];' >> $WHAT.html
echo 'var changesets_details = [' >> $WHAT.html
while read line2
do
if [ ! -z '$line2' ]; then
num=`echo "$line2" | cut -f 1 -d ' '`
comment=`grep ":$num" changesets.txt | cut -f 2 -d '#'`
echo '"'"$comment"'",' >> $WHAT.html
fi
done < $WHAT.out
echo '];' >> $WHAT.html
echo 'var changesets_count = [' >> $WHAT.html
i=0
while read line2
do
if [ ! -z '$line2' ]; then
echo $i ',' >> $WHAT.html
fi
((i++))
done < $WHAT.out
echo '];' >> $WHAT.html
cat resources/chart_footer.html >> $WHAT.html
@@ -0,0 +1,41 @@
/* setup the chart and its options */
var chart = nv.models.lineChart()
.color(d3.scale.category10().range())
.margin({left: 75, bottom: 100})
.forceX([0]).forceY([0]);
chart.x(function(datum){ return datum.r; })
.xAxis.options({
axisLabel: customSettings.XLABEL || 'Changeset',
tickFormat: d3.format('.0f')
});
chart.xAxis
.tickValues(changesets_count)
.tickFormat(function(d){return changesets[d]})
.rotateLabels(-90);
chart.y(function(datum){ return datum.v; })
.yAxis.options({
axisLabel: customSettings.YLABEL || 'GFlops'/*,
tickFormat: function(val){ return d3.format('.0f')(val) + ' GFlops'; }*/
});
chart.tooltip.headerFormatter(function(d) { return changesets[d]
+ ' <p style="font-weight:normal;text-align: left;">'
+ changesets_details[d] + "</p>"; });
//chart.useInteractiveGuideline(true);
d3.select('#chart').datum(data).call(chart);
var plot = d3.select('#chart > g');
/* setup the title */
plot.append('text')
.style('font-size', '24px')
.attr('text-anchor', 'middle').attr('x', '50%').attr('y', '20px')
.text(customSettings.TITLE || '');
/* ensure the chart is responsive */
nv.utils.windowResize(chart.update);
</script>
</body>
</html>
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
</table>
</body>
</html>
@@ -0,0 +1,42 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Eigen performance monitoring</title>
<style type="text/css">
body
{
background:#fff;
}
th {
}
img
{
width:auto;
box-shadow:0px 0px 20px #cecece;
margin: 20px 20px 20px 20px;
-moz-transform: scale(1);
-moz-transition-duration: 0.4s;
-webkit-transition-duration: 0.4s;
-webkit-transform: scale(1);
-ms-transform: scale(1);
-ms-transition-duration: 0.4s;
}
img:hover
{
box-shadow: 5px 5px 20px #dcdcdc;
-moz-transform: scale(1.1);
-moz-transition-duration: 0.4s;
-webkit-transition-duration: 0.4s;
-webkit-transform: scale(1.1);
-ms-transform: scale(1.1);
-ms-transition-duration: 0.4s;
}
</style>
</head>
<body>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,183 @@
#!/bin/bash
# ./run.sh gemm gemm_settings.txt
# ./run.sh lazy_gemm lazy_gemm_settings.txt
# ./run.sh gemv gemv_settings.txt
# ./run.sh trmv_up gemv_square_settings.txt
# ...
# Examples of environment variables to be set:
# PREFIX="haswell-fma-"
# CXX_FLAGS="-mfma"
# CXX=clang++
# Options:
# -up : enforce the recomputation of existing data, and keep best results as a merging strategy
# -s : recompute selected changesets only and keep bests
# -np : no plotting of results, just generate the data
bench=$1
settings_file=$2
if [[ "$*" =~ '-up' ]]; then
update=true
else
update=false
fi
if [[ "$*" =~ '-s' ]]; then
selected=true
else
selected=false
fi
if [[ "$*" =~ '-np' ]]; then
do_plot=false
else
do_plot=true
fi
WORKING_DIR=${PREFIX:?"default"}
if [ -z "$PREFIX" ]; then
WORKING_DIR_PREFIX="$WORKING_DIR/"
else
WORKING_DIR_PREFIX="$WORKING_DIR/$PREFIX-"
fi
echo "WORKING_DIR_PREFIX=$WORKING_DIR_PREFIX"
mkdir -p $WORKING_DIR
global_args="$*"
if $selected ; then
echo "Recompute selected changesets only and keep bests"
elif $update ; then
echo "(Re-)Compute all changesets and keep bests"
else
echo "Skip previously computed changesets"
fi
if [ ! -d "eigen_src" ]; then
git clone https://gitlab.com/libeigen/eigen.git eigen_src
else
cd eigen_src
git pull
cd ..
fi
if [ -z "$CXX" ]; then
CXX=g++
fi
function make_backup
{
if [ -f "$1.out" ]; then
mv "$1.out" "$1.backup"
fi
}
function merge
{
count1=`echo $1 | wc -w`
count2=`echo $2 | wc -w`
if [ $count1 == $count2 ]; then
a=( $1 ); b=( $2 )
res=""
for (( i=0 ; i<$count1 ; i++ )); do
ai=${a[$i]}; bi=${b[$i]}
tmp=`echo "if ($ai > $bi) $ai else $bi " | bc -l`
res="$res $tmp"
done
echo $res
else
echo $1
fi
}
function test_current
{
rev=$1
scalar=$2
name=$3
prev=""
if [ -e "$name.backup" ]; then
prev=`grep $rev "$name.backup" | cut -d ' ' -f 2-`
fi
res=$prev
count_rev=`echo $prev | wc -w`
count_ref=`cat $settings_file | wc -l`
if echo "$global_args" | grep "$rev" > /dev/null; then
rev_found=true
else
rev_found=false
fi
# echo $update et $selected et $rev_found because $rev et "$global_args"
# echo $count_rev et $count_ref
if $update || [ $count_rev != $count_ref ] || ( $selected && $rev_found ); then
echo "RUN: $CXX -O3 -DNDEBUG -march=native $CXX_FLAGS -I eigen_src $bench.cpp -DSCALAR=$scalar -o $name"
if $CXX -O3 -DNDEBUG -march=native $CXX_FLAGS -I eigen_src $bench.cpp -DSCALAR=$scalar -o $name; then
curr=`./$name $settings_file`
if [ $count_rev == $count_ref ]; then
echo "merge previous $prev"
echo "with new $curr"
else
echo "got $curr"
fi
res=`merge "$curr" "$prev"`
# echo $res
echo "$rev $res" >> $name.out
else
echo "Compilation failed, skip rev $rev"
fi
else
echo "Skip existing results for $rev / $name"
echo "$rev $res" >> $name.out
fi
}
make_backup $WORKING_DIR_PREFIX"s"$bench
make_backup $WORKING_DIR_PREFIX"d"$bench
make_backup $WORKING_DIR_PREFIX"c"$bench
cut -f1 -d"#" < changesets.txt | grep -E '[[:alnum:]]' | while read rev
do
if [ ! -z '$rev' ]; then
rev2=`echo $rev | cut -f 2 -d':'`
echo "Testing rev $rev, $rev2"
cd eigen_src
git checkout $rev2 > /dev/null
actual_rev=`git rev-parse --short HEAD`
cd ..
test_current $actual_rev float $WORKING_DIR_PREFIX"s"$bench
test_current $actual_rev double $WORKING_DIR_PREFIX"d"$bench
test_current $actual_rev "std::complex<double>" $WORKING_DIR_PREFIX"c"$bench
fi
done
echo "Float:"
cat $WORKING_DIR_PREFIX"s""$bench.out"
echo " "
echo "Double:"
cat $WORKING_DIR_PREFIX"d""$bench.out"
echo ""
echo "Complex:"
cat $WORKING_DIR_PREFIX"c""$bench.out"
echo ""
if $do_plot ; then
./make_plot.sh $WORKING_DIR_PREFIX"s"$bench $bench $settings_file
./make_plot.sh $WORKING_DIR_PREFIX"d"$bench $bench $settings_file
./make_plot.sh $WORKING_DIR_PREFIX"c"$bench $bench $settings_file
fi
@@ -0,0 +1,72 @@
#!/bin/bash
# ./runall.sh "Title"
# Examples of environment variables to be set:
# PREFIX="haswell-fma-"
# CXX_FLAGS="-mfma"
# CXX=clang++
# Options:
# -up : enforce the recomputation of existing data, and keep best results as a merging strategy
# -s : recompute selected changesets only and keep bests
# -np : no plotting of results, just generate the data
if [[ "$*" =~ '-np' ]]; then
do_plot=false
else
do_plot=true
fi
./run.sh gemm gemm_settings.txt $*
./run.sh lazy_gemm lazy_gemm_settings.txt $*
./run.sh gemv gemv_settings.txt $*
./run.sh gemvt gemv_settings.txt $*
./run.sh trmv_up gemv_square_settings.txt $*
./run.sh trmv_lo gemv_square_settings.txt $*
./run.sh trmv_upt gemv_square_settings.txt $*
./run.sh trmv_lot gemv_square_settings.txt $*
./run.sh llt gemm_square_settings.txt $*
if $do_plot ; then
# generate html file
function print_td {
echo '<td><a href="'$PREFIX'-'$1"$2"'.html"><img src="'$PREFIX'-'$1"$2"'.png" title="'$3'"></a></td>' >> $htmlfile
}
function print_tr {
echo '<tr><th colspan="3">'"$2"'</th></tr>' >> $htmlfile
echo '<tr>' >> $htmlfile
print_td s $1 float
print_td d $1 double
print_td c $1 complex
echo '</tr>' >> $htmlfile
}
if [ -n "$PREFIX" ]; then
cp resources/s1.js $PREFIX/
cp resources/s2.js $PREFIX/
htmlfile="$PREFIX/index.html"
cat resources/header.html > $htmlfile
echo '<h1>'$1'</h1>' >> $htmlfile
echo '<table>' >> $htmlfile
print_tr gemm 'C += A &middot; B &nbsp; (gemm)'
print_tr lazy_gemm 'C += A &middot; B &nbsp; (gemm lazy)'
print_tr gemv 'y += A &middot; x &nbsp; (gemv)'
print_tr gemvt 'y += A<sup>T</sup> &middot; x &nbsp; (gemv)'
print_tr trmv_up 'y += U &middot; x &nbsp; (trmv)'
print_tr trmv_upt 'y += U<sup>T</sup> &middot; x &nbsp; (trmv)'
print_tr trmv_lo 'y += L &middot; x &nbsp; (trmv)'
print_tr trmv_lot 'y += L<sup>T</sup> &middot; x &nbsp; (trmv)'
print_tr trmv_lot 'L &middot; L<sup>T<sup> = A &nbsp; (Cholesky,potrf)'
cat resources/footer.html >> $htmlfile
fi
fi

Some files were not shown because too many files have changed in this diff Show More