并行化特征密集映射矩阵向量积

时间:2017-08-22 21:43:35

标签: c++ multithreading eigen

我已成功为稀疏矩阵向量产品启用多线程,但我无法并行化涉及两个密集映射的产品。只生成一个线程。起初我认为可能缺乏对地图的并行支持,但是复制到普通矩阵和向量然后获取产品并不能解决问题。我写了一个简短的示例程序,基于我写的那个来演示问题。我很确定这不是编译问题,因为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);
}

0 个答案:

没有答案
相关问题