Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ci skip] Speed up expand2b benchmark #470

Closed
wants to merge 13 commits into from
@@ -58,6 +58,8 @@ benchmarks/eval_double1
benchmarks/expand1
benchmarks/expand2
benchmarks/expand2b
benchmarks/expand2c
benchmarks/expand2d
benchmarks/expand3
benchmarks/matrix_add1
benchmarks/matrix_add2
@@ -24,6 +24,9 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
"${CMAKE_CXX_FLAGS_RELEASE} -Wno-unused-parameter")
endif()

set(CMAKE_CXX_FLAGS_RELEASE
"${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")

if (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -Wno-unused-parameter -ggdb")
@@ -137,7 +140,7 @@ if (WITH_PTHREAD)
endif()

if (WITH_BOOST)
find_package(Boost REQUIRED COMPONENTS date_time filesystem system)
find_package(Boost REQUIRED COMPONENTS date_time filesystem system serialization)
include_directories(${Boost_INCLUDE_DIRS})
set(LIBS ${LIBS} ${Boost_LIBRARIES})
set(HAVE_SYMENGINE_BOOST yes)
@@ -17,6 +17,12 @@ target_link_libraries(expand2 symengine)
add_executable(expand2b expand2b.cpp)
target_link_libraries(expand2b symengine)

add_executable(expand2c expand2c.cpp)
target_link_libraries(expand2c symengine)

add_executable(expand2d expand2d.cpp)
target_link_libraries(expand2d symengine)

add_executable(expand3 expand3.cpp)
target_link_libraries(expand3 symengine)

@@ -0,0 +1,86 @@
#include <iostream>
#include <chrono>

#include "basic.h"
#include "add.h"
#include "symbol.h"
#include "dict.h"
#include "integer.h"
#include "mul.h"
#include "pow.h"
#include "rings.h"
#include "monomials.h"

using SymEngine::Basic;
using SymEngine::Symbol;
using SymEngine::symbol;
using SymEngine::umap_basic_num;
using SymEngine::Integer;
using SymEngine::integer;
using SymEngine::expr2poly;
using SymEngine::poly_mul;
using SymEngine::poly_mul2;
using SymEngine::packed2poly;
using SymEngine::poly2packed;
using SymEngine::umap_vec_mpz;
using SymEngine::umap_ull_mpz;
using SymEngine::RCP;
using SymEngine::rcp;
using SymEngine::print_stack_on_segfault;

int main(int argc, char* argv[])
{
print_stack_on_segfault();
RCP<const Basic> x = symbol("x");
RCP<const Basic> y = symbol("y");
RCP<const Basic> z = symbol("z");
RCP<const Basic> w = symbol("w");
RCP<const Basic> i15 = integer(15);

RCP<const Basic> e, f1, f2;

e = pow(add(add(add(x, y), z), w), i15);
f1 = expand(e);
f2 = expand(add(e, w));

umap_basic_num syms;
insert(syms, x, integer(0));
insert(syms, y, integer(1));
insert(syms, z, integer(2));
insert(syms, w, integer(3));

umap_vec_mpz P1, P2, C;

expr2poly(f1, syms, P1);
expr2poly(f2, syms, P2);

umap_ull_mpz p, q, r;

poly2packed(P1, p);
poly2packed(P2, q);

std::cout << "poly_mul start" << std::endl;
auto t1 = std::chrono::high_resolution_clock::now();
poly_mul2(p, q, r);
auto t2 = std::chrono::high_resolution_clock::now();
std::cout << "poly_mul stop" << std::endl;

packed2poly(r, syms, C);

/*
std::cout << *e << std::endl;
std::cout << *f1 << std::endl;
std::cout << P1 << std::endl;
std::cout << *f2 << std::endl;
std::cout << P2 << std::endl;
std::cout << "RESULT:" << std::endl;
std::cout << C << std::endl;
*/
std::cout
<< std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count()
<< "ms" << std::endl;
std::cout << "number of terms: "
<< C.size() << std::endl;

return 0;
}
@@ -0,0 +1,97 @@
#include <iostream>
#include <chrono>

#include "basic.h"
#include "add.h"
#include "symbol.h"
#include "dict.h"
#include "integer.h"
#include "mul.h"
#include "pow.h"
#include "rings.h"
#include "monomials.h"

using SymEngine::Basic;
using SymEngine::Symbol;
using SymEngine::symbol;
using SymEngine::umap_basic_num;
using SymEngine::Integer;
using SymEngine::integer;
using SymEngine::expr2poly;
using SymEngine::poly_mul;
using SymEngine::poly_mul2;
using SymEngine::poly_mul3;
using SymEngine::packed2poly;
using SymEngine::poly2packed;
using SymEngine::poly2hashset;
using SymEngine::hashset2poly;
using SymEngine::umap_vec_mpz;
using SymEngine::umap_ull_mpz;
using SymEngine::hash_set;
using SymEngine::RCP;
using SymEngine::rcp;
using SymEngine::print_stack_on_segfault;

int main(int argc, char* argv[])
{
print_stack_on_segfault();
RCP<const Basic> x = symbol("x");
RCP<const Basic> y = symbol("y");
RCP<const Basic> z = symbol("z");
RCP<const Basic> w = symbol("w");
RCP<const Basic> i15 = integer(15);

RCP<const Basic> e, f1, f2;

e = pow(add(add(add(x, y), z), w), i15);
f1 = expand(e);
f2 = expand(add(e, w));

umap_basic_num syms;
insert(syms, x, integer(0));
insert(syms, y, integer(1));
insert(syms, z, integer(2));
insert(syms, w, integer(3));

umap_vec_mpz P1, P2, C;

expr2poly(f1, syms, P1);
expr2poly(f2, syms, P2);

hash_set l, m, n;

poly2hashset(P1, l);
poly2hashset(P2, m);

n.rehash(10000);

std::cout << "poly_mul start" << std::endl;
auto t1 = std::chrono::high_resolution_clock::now();
poly_mul3(l, m, n);
auto t2 = std::chrono::high_resolution_clock::now();
std::cout << "poly_mul stop" << std::endl;

auto s = n.evaluate_sparsity();
for (const auto &p: s) {
std::cout << p.first << ',' << p.second << '\n';
}

hashset2poly(n, syms, C);

/*
std::cout << *e << std::endl;
std::cout << *f1 << std::endl;
std::cout << P1 << std::endl;
std::cout << *f2 << std::endl;
std::cout << P2 << std::endl;
std::cout << "RESULT:" << std::endl;
std::cout << C << std::endl;
*/
std::cout
<< std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count()
<< "ms" << std::endl;
std::cout << "number of terms: "
<< C.size() << std::endl;

return 0;
}
@@ -51,6 +51,40 @@ inline std::ostream& print_vec_rcp(std::ostream& out, T& d)
return out;
}

unsigned long long pack_vec_int(const vec_int &a) {
//Equal bits, not necessary. if the total(t) were allocated more
//bits may lead to more optimization.
uint n_var = a.size();
uint b = 64 / (n_var + 1) ;
unsigned long long ans = 0;
int mul = 0;
long long t = 0;
for (uint i = 0; i < n_var; i++) {
ans += static_cast<unsigned long long>(a[i])<<mul;
t += a[i];
mul += b;
}
ans += static_cast<unsigned long long>(t)<<mul;
return ans;
}

bool if_pack_vec_int(const vec_int &a) {
uint n_var = a.size();
if (!(n_var < 32))
return false;
uint b = 64 / (n_var + 1) ;
long long max = 1<<b;
long long t = 0;
for (uint i = 0; i < n_var; i++) {
if (!(a[i] >= 0) || !(a[i] < max))
return false;
t += a[i];
}
if (!(t >= 0) || !(t < max))
return false;
return true;
}

} // SymEngine


@@ -79,6 +113,11 @@ std::ostream& operator<<(std::ostream& out, const SymEngine::umap_vec_mpz& d)
return print_map(out, d);
}

std::ostream& operator<<(std::ostream& out, const SymEngine::umap_ull_mpz& d)
{
return SymEngine::print_map(out, d);
}

std::ostream& operator<<(std::ostream& out, const SymEngine::map_basic_num& d)
{
return print_map_rcp(out, d);
@@ -10,6 +10,23 @@

#include <gmpxx.h>

#include <piranha/piranha.hpp>
#include <boost/functional/hash.hpp>

namespace std
{
template <>
struct hash<std::pair<unsigned long long, piranha::integer>>
{
typedef size_t result_type;
typedef std::pair<unsigned long long,piranha::integer> argument_type;
result_type operator()(const argument_type &p) const noexcept
{
return std::hash<unsigned long long>()(p.first);
}
};
}

namespace SymEngine {

class Basic;
@@ -20,10 +37,36 @@ struct RCPBasicKeyEq;
struct RCPBasicKeyLess;
struct RCPIntegerKeyLess;

struct my_pair
{
long long first;
mutable piranha::integer second;
};

typedef struct
{
typedef size_t result_type;
typedef my_pair argument_type;
result_type operator()(const argument_type &p) const noexcept
{
return std::hash<long long>()(p.first);
}
} my_hash;

typedef struct
{
//! \return true if `x==y`
inline bool operator() (const my_pair &x, const my_pair &y) const {
return x.first == y.first;
}
} hash_eq;

typedef std::unordered_map<RCP<const Basic>, RCP<const Number>,
RCPBasicHash, RCPBasicKeyEq> umap_basic_num;
typedef std::unordered_map<RCP<const Basic>, RCP<const Basic>,
RCPBasicHash, RCPBasicKeyEq> umap_basic_basic;
typedef std::unordered_map<long long, piranha::integer> umap_ull_mpz;
typedef piranha::hash_set<my_pair, my_hash, hash_eq> hash_set;

typedef std::vector<int> vec_int;
typedef std::vector<RCP<const Basic>> vec_basic;
@@ -72,6 +115,10 @@ int vec_basic_compare(const vec_basic &a, const vec_basic &b);
//! \return -1, 0, 1 for a < b, a == b, a > b
int map_uint_mpz_compare(const map_uint_mpz &a, const map_uint_mpz &b);

//! kronecker packing of exponents
unsigned long long pack_vec_int(const vec_int &a);
//! check if the packing is possible
bool if_pack_vec_int(const vec_int &a);

//! Part of umap_vec_mpz:
typedef struct
@@ -108,6 +155,7 @@ std::ostream& operator<<(std::ostream& out, const SymEngine::map_basic_num& d);
std::ostream& operator<<(std::ostream& out, const SymEngine::map_basic_basic& d);
std::ostream& operator<<(std::ostream& out, const SymEngine::umap_basic_basic& d);
std::ostream& operator<<(std::ostream& out, const SymEngine::vec_basic& d);
std::ostream& operator<<(std::ostream& out, const SymEngine::umap_ull_mpz& d);

#endif

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.