我已成功为稀疏矩阵向量产品启用多线程,但我无法并行化涉及两个密集映射的产品。只生成一个线程。起初我认为可能缺乏对地图的并行支持,但是复制到普通矩阵和向量然后获取产品并不能解决问题。我写了一个简短的示例程序,基于我写的那个来演示问题。我很确定这不是编译问题,因为Eigen::nbThreads()
输出正确数量的线程。谢谢你的帮助。
生成文件
EXEDIR = ./targets/darwin
CC = clang-omp++
CXX = clang-omp++
CFLAGS := -std=c++11 -Wall -pipe -O3 -ffast-math \
-funsafe-math-optimizations -march=native -mtune=native \
-pedantic -Wno-unused-variable -fopenmp -I/usr/local/include/eigen3
LDFLAGS := -std=c++11 -fopenmp -lpthread -lboost_date_time-mt -lboost_thread-mt \
-lboost_filesystem-mt -lboost_system-mt -lboost_program_options \
-I/usr/local/include/eigen3
SIMULATIONS=$(EXEDIR)/main
LOCALOBJECTS=network.o
.SECONDARY:
all: $(SIMULATIONS)
$(EXEDIR)/%: %.o $(LOCALOBJECTS)
$(CC) $(CFLAGS) $(LOCALOBJECTS) $< $(LDFLAGS) -o $@
%.o : %.cpp
$(CC) $(CFLAGS) -c $<
clean:
rm -f *.o $(SIMULATIONS)
的main.cpp
#include "network.h"
int main(int ac, char* av[]) {
run();
return 0;
};
network.h
#include <iostream>
#include <random>
#include <functional>
#include <math.h>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <boost/numeric/odeint.hpp>
#include <boost/numeric/odeint/external/eigen/eigen.hpp>
#include <boost/random.hpp>
using namespace std;
using namespace Eigen;
using namespace boost::numeric::odeint;
typedef Eigen::VectorXf container_type;
float phi0 (float x, float g, float o);
struct observer
{
observer() {}
void operator()( container_type &x , float t ) {}
};
struct network
{
boost::mt19937 rng;
container_type x, tau;
Eigen::Map<container_type> r;
Eigen::Map<Eigen::MatrixXf> W, W_EE, W_II, W_EI, W_IE;
function <float (float)> phi_E, phi_I;
int N, N_E, N_I;
network() :
x(4001*4000), tau(4000),
r(NULL, NULL),
W(NULL, NULL, NULL),
W_EE(NULL, NULL, NULL), W_II(NULL, NULL, NULL),
W_EI(NULL, NULL, NULL), W_IE(NULL, NULL, NULL)
{
N = 4000;
N_E = 4000;
N_I = 0;
new (&r) Eigen::Map<container_type>(x.head(N).data(), N);
new (&W) Eigen::Map<Eigen::MatrixXf>( x.tail(N*N).data(), N, N);
new (&W_EE) Eigen::Map<Eigen::MatrixXf>( W.topLeftCorner(N_E,N_E).data(), N_E, N_E);
new (&W_EI) Eigen::Map<Eigen::MatrixXf>( W.topRightCorner(N_E,N_I).data(), N_E, N_I);
new (&W_IE) Eigen::Map<Eigen::MatrixXf>( W.bottomLeftCorner(N_I,N_E).data(), N_I, N_E);
new (&W_II) Eigen::Map<Eigen::MatrixXf>(W.bottomRightCorner(N_I,N_I).data(), N_I, N_I);
x.setZero(N + N*N);
tau.head(N_E).setConstant(10e-3);
tau.tail(N_I).setConstant(10e-3);
select_transfer_function(phi_E, 0);
select_transfer_function(phi_I, 0);
cout << "Building connectivity... " << std::flush;
generate_gaussian_connectivity( W_EE, 0, 1.1/sqrt(4000) );
cout << "Done.\n" << std::flush;
cout << "Setting initial condition... " << std::flush;
container_type z(N);
boost::normal_distribution<> normal( 0, 1 );
boost::variate_generator< boost::mt19937&, boost::normal_distribution<> > gen( rng , normal );
gen.engine().seed(42);
z = z.unaryExpr([&gen, this](float a){return static_cast<float>(gen());});
r = z;
cout << "Done.\n" << std::flush;
}
void select_transfer_function( function <float (float)>& phi, unsigned int p_phi )
{
phi = std::bind(&phi0, placeholders::_1, 1, 0);
}
void generate_gaussian_connectivity( Eigen::Map<Eigen::MatrixXf>& W_AB, double J_mu, double J_sigma )
{
boost::normal_distribution<> normal( J_mu, J_sigma );
boost::variate_generator< boost::mt19937&, boost::normal_distribution<> > gen( rng , normal );
W_AB = W_AB.unaryExpr([&gen, this](float a){return static_cast<float>(gen());});
W_AB.diagonal().setZero();
}
void operator()( container_type &x , container_type &dxdt , double t ) const
{
Map<Eigen::VectorXf> drdt(dxdt.head(N).data(), N);
Eigen::VectorXf rate = W * r;
rate.head(N_E) = (rate.head(N_E)).unaryExpr(phi_E);
rate.tail(N_I) = (rate.tail(N_I)).unaryExpr(phi_I);
drdt = ((rate - r).array()/tau.array()).matrix();
}
};
void run();
network.cpp
#include "network.h"
// ---- Transfer functions ----------
// Hyperbolic tangent
float phi0(float x, float g, float o) {
return o + tanh(g*x);
}
// ---- Network structure ------------
void run()
{
// Enable multi-threading
Eigen::setNbThreads(6);
cout << "Threads: " << Eigen::nbThreads( ) << '\n' << std::flush;
network net;
observer obs;
integrate_const( euler< container_type >(), boost::ref( net ), net.x, 0.0, 2.0, 1e-3, obs);
}