<commit_before>//---------------------------------------------------------------------------//
//!
//! \file   MonteCarlo_BatchedDistributedParticleSimulationManager_def.hpp
//! \author Alex Robinson
//! \brief  The batched distributed particle simulation manager class def.
//!
//---------------------------------------------------------------------------//

#ifndef FACEMC_BATCHED_DISTRIBUTED_PARTICLE_SIMULATION_MANAGER_DEF_HPP
#define FACEMC_BATCHED_DISTRIBUTED_PARTICLE_SIMULATION_MANAGER_DEF_HPP

// Trilinos Includes
#include <Teuchos_GlobalMPISession.hpp>

// MPI Includes
#ifdef HAVE_FRENSIE_MPI
#endif

// FRENSIE Includes
#include "Utility_ContractException.hpp"
#include "FRENSIE_mpi_config.hpp"

namespace MonteCarlo{

// Constructor
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::BatchedDistributedParticleSimulationManager(
      const Teuchos::RCP<const Teuchos::Comm<unsigned long long> >& comm,
	    const int root_process,
	    const unsigned number_of_histories,
	    const unsigned start_history,
	    const unsigned previously_completed_histories,
	    const double previous_run_time )
  : ParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>( number_of_histories, start_history, previously_completed_histories, previous_run_time ),
    d_comm( comm ),
    d_root_process( root_process )
{
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );
  // Make sure the communicator is valid
  testPrecondition( !comm.is_null() );
}

// Run the simulation set up by the user
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
void BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::runSimulation()
{
#ifdef HAVE_FRENSIE_MPI
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );

  if( d_comm->getRank() == d_root_process )
  {
    std::cout << "Starting simulation ... ";
    std::cout.flush();
  }

  // Set up the random number generator for the number of threads requested
  Utility::RandomNumberGenerator::createStreams();

  // Enable geometry thread support
  GMI::enableThreadSupport(
	         Utility::GlobalOpenMPSession::getRequestedNumberOfThreads() );

  // Enable estimator thread support
  EMI::enableThreadSupport(
		 Utility::GlobalOpenMPSession::getRequestedNumberOfThreads() );

  // Cast the communicator to an MpiComm object
  Teuchos::RCP<const Teuchos::MpiComm<unsigned long long> > mpi_comm =
    Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<unsigned long long> >(
								      d_comm );
  mpi_comm->barrier();

  // Set the start time
  this->setStartTime( ::MPI_Wtime() );

  // The number of batches that need to be run
  unsigned long long number_of_batches = 25*mpi_comm->getSize();

  // The size of each batch (except possibly the last batch)
  unsigned long long batch_size =
    this->getNumberOfHistories()/number_of_batches;

  // The current batch number
  unsigned batch_number = 0;

  // The batch info array that will be passed to workers
  unsigned long long batch_info[2];

  // The MPI error code
  int return_value;

  while( true )
  {
    // The root process will handle all batch requests and data collection
    if( mpi_comm->getRank() == d_root_process )
    {
      // All batches complete - send quit message to workers
      if( batch_number == number_of_batches )
      {
	for( int i = 0; i < mpi_comm->getSize(); ++i )
	{
	  if( i != d_root_process )
	  {
	    int message;

	    // The recv request
	    MPI_Request raw_recv_request;

	    return_value = ::MPI_Irecv( &message,
					1,
					MPI_INT,
					i,
					mpi_comm->getTag(),
					*mpi_comm->getRawMpiComm(),
					&raw_recv_request );

	    TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			      std::runtime_error,
			      "Error: unable to get receive message on root "
			      "process " << d_root_process << " from worker "
			      "process " << i << "! "
			      "MPI_Irecv failed with the following error: "
			      << Teuchos::mpiErrorCodeToString(return_value) );

	    // The quit message
	    unsigned long long quit = 1;

	    // The send request
	    MPI_Request raw_send_request;

	    return_value = ::MPI_Isend( &quit,
					1,
					MPI_UNSIGNED_LONG_LONG,
					i,
					mpi_comm->getTag(),
					*mpi_comm->getRawMpiComm(),
					&raw_send_request );

	    TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
				std::runtime_error,
				"Error: unable to send batch info from "
				"root process " << d_root_process <<
				"to worker process " << i << "! "
				"MPI_Isend failed with the following error: "
				<< Teuchos::mpiErrorCodeToString(return_value));
	  }
	}

	break;
      }
      // Keep assigning batches to workers until all have been completed
      else
      {
	// Probe for an idle worker
	int* message_waiting = NULL;
	MPI_Status raw_status;

	return_value = MPI_Iprobe( MPI_ANY_SOURCE,
				   mpi_comm->getTag(),
				   *mpi_comm->getRawMpiComm(),
				   message_waiting,
				   &raw_status );

	TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			    std::runtime_error,
			    "Error: unable to perform mpi probe in "
			    "batched distributed particle simulation manager! "
			    "MPI_Probe failed with the following error: "
			    << Teuchos::mpiErrorCodeToString( return_value ) );

	// Idle worker found - assign it a new batch
	if( message_waiting )
	{
	  int worker_rank = raw_status.MPI_SOURCE;
	  int message_tag = raw_status.MPI_TAG;
	  int message;

	  // Initiate handshake with worker
	  return_value = ::MPI_Recv( &message,
				     1,
				     MPI_INT,
				     worker_rank,
				     message_tag,
				     *mpi_comm->getRawMpiComm(),
				     MPI_STATUS_IGNORE );

	  TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			      std::runtime_error,
			      "Error: unable to get receive message on root "
			      "process " << d_root_process << " from worker "
			      "process " << worker_rank << "! "
			      "MPI_Recv failed with the following error: "
			      << Teuchos::mpiErrorCodeToString(return_value) );

	  // Set the batch start history
	  batch_info[0] = batch_number*batch_size;

	  // Set the batch end history
	  batch_info[1] = batch_info[0] + batch_size;

	  // Check if the size of the last batch is correct
	  if( batch_number == number_of_batches - 1 )
	  {
	    batch_info[1] +=
	      this->getNumberOfHistories()-number_of_batches*batch_size;
	  }

	  // Pass new start history to worker
	  return_value = ::MPI_Send( batch_info,
				     2,
				     MPI_UNSIGNED_LONG_LONG,
				     worker_rank,
				     mpi_comm->getTag(),
				     *mpi_comm->getRawMpiComm() );

	  TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			      std::runtime_error,
			      "Error: unable to send batch info from "
			      "root process " << d_root_process << "to worker "
			      "process " << worker_rank << "! "
			      "MPI_Send failed with the following error: "
			      << Teuchos::mpiErrorCodeToString(return_value) );

	  // Increment the batch number
	  ++batch_number;
	}
      }
    }
    // The workers
    else
    {
      int ready_for_work = 1;

      // Humbly request a new batch - wait patiently until you get one
      return_value = ::MPI_Send( &ready_for_work,
				 1,
				 MPI_INT,
				 d_root_process,
				 mpi_comm->getTag(),
				 *mpi_comm->getRawMpiComm() );

      TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			  std::runtime_error,
			  "Error: worker process "
			  << mpi_comm->getRank() <<
			  " unable to request work from root process "
			  << d_root_process << "! "
			  "MPI_Send failed with the following error: "
			  << Teuchos::mpiErrorCodeToString( return_value ) );

      MPI_Status raw_batch_status;

      // You've been given a new batch to work on!
      return_value = ::MPI_Recv( batch_info,
				 2,
				 MPI_UNSIGNED_LONG_LONG,
				 d_root_process,
				 mpi_comm->getTag(),
				 *mpi_comm->getRawMpiComm(),
				 &raw_batch_status );

      TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			  std::runtime_error,
			  "Error: worker process "
			  << mpi_comm->getRank() <<
			  " unable to receive work from root process "
			  << d_root_process << "! "
			  "MPI_Recv failed with the following error: "
			  << Teuchos::mpiErrorCodeToString( return_value ) );

      int exit_condition;

      // Check if the exit condition was sent
      return_value = ::MPI_Get_count( &raw_batch_status,
				      MPI_UNSIGNED_LONG_LONG,
				      &exit_condition );

      // Run the simulation batch
      if( exit_condition != 1 )
	this->runSimulationBatch( batch_info[0], batch_info[1] );
      // All of the batches are complete
      else
	break;
    }
  }

  // Wait for all processes to get to this point
  mpi_comm->barrier();

  // Perform a reduction of the estimator data on the root process
  EMI::reduceEstimatorData( d_comm, d_root_process );

  // Set the end time
  this->setEndTime( ::MPI_Wtime() );

  if( d_comm->getRank() == d_root_process )
    std::cout << "done." << std::endl;
#else
  if( d_comm->getRank() == d_root_process )
  {
    std::cout << "Simulation cannot be run without building with MPI!"
	      << std::endl;
  }
#endif // end HAVE_FRENSIE_MPI
}

// Print the data in all estimators to the desired stream
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
void BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::printSimulationSummary( std::ostream &os ) const
{
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );

  if( d_comm->getRank() == d_root_process )
  {
    ParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::printSimulationSummary( os );
  }
}

// Export the simulation data (to an hdf5 file)
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
void BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::exportSimulationData( const std::string& data_file_name ) const
{
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );

  if( d_comm->getRank() == d_root_process )
  {
    ParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::exportSimulationData( data_file_name );
  }
}

// Signal handler
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
void BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::signalHandler(int signal)
{
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );

  if( d_comm->getRank() == d_root_process )
  {
    ParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::signalHandler( signal );
  }
}

} // end MonteCarlo namespace

#endif // end FACEMC_BATCHED_DISTRIBUTED_PARTICLE_SIMULATION_MANAGER_DEF_HPP

//---------------------------------------------------------------------------//
// end MonteCarlo_BatchedDistributedParticleSimulationManager_def.hpp
//---------------------------------------------------------------------------//
<commit_msg>Fixed MPI_Iprobe call<commit_after>//---------------------------------------------------------------------------//
//!
//! \file   MonteCarlo_BatchedDistributedParticleSimulationManager_def.hpp
//! \author Alex Robinson
//! \brief  The batched distributed particle simulation manager class def.
//!
//---------------------------------------------------------------------------//

#ifndef FACEMC_BATCHED_DISTRIBUTED_PARTICLE_SIMULATION_MANAGER_DEF_HPP
#define FACEMC_BATCHED_DISTRIBUTED_PARTICLE_SIMULATION_MANAGER_DEF_HPP

// Trilinos Includes
#include <Teuchos_GlobalMPISession.hpp>

// MPI Includes
#ifdef HAVE_FRENSIE_MPI
#endif

// FRENSIE Includes
#include "Utility_ContractException.hpp"
#include "FRENSIE_mpi_config.hpp"

namespace MonteCarlo{

// Constructor
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::BatchedDistributedParticleSimulationManager(
      const Teuchos::RCP<const Teuchos::Comm<unsigned long long> >& comm,
	    const int root_process,
	    const unsigned number_of_histories,
	    const unsigned start_history,
	    const unsigned previously_completed_histories,
	    const double previous_run_time )
  : ParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>( number_of_histories, start_history, previously_completed_histories, previous_run_time ),
    d_comm( comm ),
    d_root_process( root_process )
{
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );
  // Make sure the communicator is valid
  testPrecondition( !comm.is_null() );
}

// Run the simulation set up by the user
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
void BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::runSimulation()
{
#ifdef HAVE_FRENSIE_MPI
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );

  if( d_comm->getRank() == d_root_process )
  {
    std::cout << "Starting simulation ... ";
    std::cout.flush();
  }

  // Set up the random number generator for the number of threads requested
  Utility::RandomNumberGenerator::createStreams();

  // Enable geometry thread support
  GMI::enableThreadSupport(
	         Utility::GlobalOpenMPSession::getRequestedNumberOfThreads() );

  // Enable estimator thread support
  EMI::enableThreadSupport(
		 Utility::GlobalOpenMPSession::getRequestedNumberOfThreads() );

  // Cast the communicator to an MpiComm object
  Teuchos::RCP<const Teuchos::MpiComm<unsigned long long> > mpi_comm =
    Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<unsigned long long> >(
								      d_comm );
  mpi_comm->barrier();

  // Set the start time
  this->setStartTime( ::MPI_Wtime() );

  // The number of batches that need to be run
  unsigned long long number_of_batches = 25*mpi_comm->getSize();

  // The size of each batch (except possibly the last batch)
  unsigned long long batch_size =
    this->getNumberOfHistories()/number_of_batches;

  // The current batch number
  unsigned batch_number = 0;

  // The batch info array that will be passed to workers
  unsigned long long batch_info[2];

  // The MPI error code
  int return_value;

  while( true )
  {
    // The root process will handle all batch requests and data collection
    if( mpi_comm->getRank() == d_root_process )
    {
      // All batches complete - send quit message to workers
      if( batch_number == number_of_batches )
      {
	for( int i = 0; i < mpi_comm->getSize(); ++i )
	{
	  if( i != d_root_process )
	  {
	    int message;

	    // The recv request
	    MPI_Request raw_recv_request;

	    return_value = ::MPI_Irecv( &message,
					1,
					MPI_INT,
					i,
					mpi_comm->getTag(),
					*mpi_comm->getRawMpiComm(),
					&raw_recv_request );

	    TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			      std::runtime_error,
			      "Error: unable to get receive message on root "
			      "process " << d_root_process << " from worker "
			      "process " << i << "! "
			      "MPI_Irecv failed with the following error: "
			      << Teuchos::mpiErrorCodeToString(return_value) );

	    // The quit message
	    unsigned long long quit = 1;

	    // The send request
	    MPI_Request raw_send_request;

	    return_value = ::MPI_Isend( &quit,
					1,
					MPI_UNSIGNED_LONG_LONG,
					i,
					mpi_comm->getTag(),
					*mpi_comm->getRawMpiComm(),
					&raw_send_request );

	    TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
				std::runtime_error,
				"Error: unable to send batch info from "
				"root process " << d_root_process <<
				"to worker process " << i << "! "
				"MPI_Isend failed with the following error: "
				<< Teuchos::mpiErrorCodeToString(return_value));
	  }
	}

	break;
      }
      // Keep assigning batches to workers until all have been completed
      else
      {
	// Probe for an idle worker
	int message_waiting = false;
	MPI_Status raw_status;

	return_value = MPI_Iprobe( MPI_ANY_SOURCE,
				   mpi_comm->getTag(),
				   *mpi_comm->getRawMpiComm(),
				   &message_waiting,
				   &raw_status );

	TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			    std::runtime_error,
			    "Error: unable to perform mpi probe in "
			    "batched distributed particle simulation manager! "
			    "MPI_Probe failed with the following error: "
			    << Teuchos::mpiErrorCodeToString( return_value ) );

	// Idle worker found - assign it a new batch
	if( message_waiting )
	{
	  int worker_rank = raw_status.MPI_SOURCE;
	  int message_tag = raw_status.MPI_TAG;
	  int message;

	  // Initiate handshake with worker
	  return_value = ::MPI_Recv( &message,
				     1,
				     MPI_INT,
				     worker_rank,
				     message_tag,
				     *mpi_comm->getRawMpiComm(),
				     MPI_STATUS_IGNORE );

	  TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			      std::runtime_error,
			      "Error: unable to get receive message on root "
			      "process " << d_root_process << " from worker "
			      "process " << worker_rank << "! "
			      "MPI_Recv failed with the following error: "
			      << Teuchos::mpiErrorCodeToString(return_value) );

	  // Set the batch start history
	  batch_info[0] = batch_number*batch_size;

	  // Set the batch end history
	  batch_info[1] = batch_info[0] + batch_size;

	  // Check if the size of the last batch is correct
	  if( batch_number == number_of_batches - 1 )
	  {
	    batch_info[1] +=
	      this->getNumberOfHistories()-number_of_batches*batch_size;
	  }

	  // Pass new start history to worker
	  return_value = ::MPI_Send( batch_info,
				     2,
				     MPI_UNSIGNED_LONG_LONG,
				     worker_rank,
				     mpi_comm->getTag(),
				     *mpi_comm->getRawMpiComm() );

	  TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			      std::runtime_error,
			      "Error: unable to send batch info from "
			      "root process " << d_root_process << "to worker "
			      "process " << worker_rank << "! "
			      "MPI_Send failed with the following error: "
			      << Teuchos::mpiErrorCodeToString(return_value) );

	  // Increment the batch number
	  ++batch_number;
	}
      }
    }
    // The workers
    else
    {
      int ready_for_work = 1;

      // Humbly request a new batch - wait patiently until you get one
      return_value = ::MPI_Send( &ready_for_work,
				 1,
				 MPI_INT,
				 d_root_process,
				 mpi_comm->getTag(),
				 *mpi_comm->getRawMpiComm() );

      TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			  std::runtime_error,
			  "Error: worker process "
			  << mpi_comm->getRank() <<
			  " unable to request work from root process "
			  << d_root_process << "! "
			  "MPI_Send failed with the following error: "
			  << Teuchos::mpiErrorCodeToString( return_value ) );

      MPI_Status raw_batch_status;

      // You've been given a new batch to work on!
      return_value = ::MPI_Recv( batch_info,
				 2,
				 MPI_UNSIGNED_LONG_LONG,
				 d_root_process,
				 mpi_comm->getTag(),
				 *mpi_comm->getRawMpiComm(),
				 &raw_batch_status );

      TEST_FOR_EXCEPTION( return_value != MPI_SUCCESS,
			  std::runtime_error,
			  "Error: worker process "
			  << mpi_comm->getRank() <<
			  " unable to receive work from root process "
			  << d_root_process << "! "
			  "MPI_Recv failed with the following error: "
			  << Teuchos::mpiErrorCodeToString( return_value ) );

      int exit_condition;

      // Check if the exit condition was sent
      return_value = ::MPI_Get_count( &raw_batch_status,
				      MPI_UNSIGNED_LONG_LONG,
				      &exit_condition );

      // Run the simulation batch
      if( exit_condition != 1 )
	this->runSimulationBatch( batch_info[0], batch_info[1] );
      // All of the batches are complete
      else
	break;
    }
  }

  // Wait for all processes to get to this point
  mpi_comm->barrier();

  // Perform a reduction of the estimator data on the root process
  EMI::reduceEstimatorData( d_comm, d_root_process );

  // Set the end time
  this->setEndTime( ::MPI_Wtime() );

  if( d_comm->getRank() == d_root_process )
    std::cout << "done." << std::endl;
#else
  if( d_comm->getRank() == d_root_process )
  {
    std::cout << "Simulation cannot be run without building with MPI!"
	      << std::endl;
  }
#endif // end HAVE_FRENSIE_MPI
}

// Print the data in all estimators to the desired stream
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
void BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::printSimulationSummary( std::ostream &os ) const
{
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );

  if( d_comm->getRank() == d_root_process )
  {
    ParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::printSimulationSummary( os );
  }
}

// Export the simulation data (to an hdf5 file)
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
void BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::exportSimulationData( const std::string& data_file_name ) const
{
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );

  if( d_comm->getRank() == d_root_process )
  {
    ParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::exportSimulationData( data_file_name );
  }
}

// Signal handler
template<typename GeometryHandler,
	 typename SourceHandler,
	 typename EstimatorHandler,
	 typename CollisionHandler>
void BatchedDistributedParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::signalHandler(int signal)
{
  // Make sure the global MPI session has been initialized
  testPrecondition( Teuchos::GlobalMPISession::mpiIsInitialized() );
  testPrecondition( !Teuchos::GlobalMPISession::mpiIsFinalized() );

  if( d_comm->getRank() == d_root_process )
  {
    ParticleSimulationManager<GeometryHandler,SourceHandler,EstimatorHandler,CollisionHandler>::signalHandler( signal );
  }
}

} // end MonteCarlo namespace

#endif // end FACEMC_BATCHED_DISTRIBUTED_PARTICLE_SIMULATION_MANAGER_DEF_HPP

//---------------------------------------------------------------------------//
// end MonteCarlo_BatchedDistributedParticleSimulationManager_def.hpp
//---------------------------------------------------------------------------//
<|endoftext|>


<commit_before>#ifndef _SNARKFRONT_SECURE_HASH_STD_HPP_
#define _SNARKFRONT_SECURE_HASH_STD_HPP_

#include <cassert>
#include <cstdint>
#include <ostream>
#include <string>
#include <vector>

#include <snarkfront/DataBuffer.hpp>

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// FIPS PUB 180-4, NIST March 2012
//
// Algorithm     Message Size   Block Size   Word Size   Message Digest
//               (bits)         (bits)       (bits)      Size (bits)
// SHA-1         < 2^64         512          32          160
// SHA-224       < 2^64         512          32          224
// SHA-256       < 2^64         512          32          256
// SHA-384       < 2^128        1024         64          384
// SHA-512       < 2^128        1024         64          512
// SHA-512/224   < 2^128        1024         64          224
// SHA-512/256   < 2^128        1024         64          256
//

enum class SHA_BlockSize {
    BLOCK_512, // for: SHA-1, SHA-224, SHA-256
    BLOCK_1024 // for: SHA-384, SHA-512, SHA-512/224, SHA-512/256
};

template <typename CRTP, SHA_BlockSize BLK, typename MSG>
class SHA_Base
{
public:
    virtual ~SHA_Base() = default;

    static void padMessage(DataBuffer<ClearText>& buf) {
        const std::size_t msgLengthBits = buf->sizeBits();

        buf.push8(0x80); // append bit "1" to end of the message

        // keep padding zero bits to the length block at the end
        const size_t stopPadBits = blockSizeBits() - 2 * wordSizeBits();
        while (stopPadBits != buf->sizeBits() % blockSizeBits()) {
            buf.push8(0x00);
        }

        // append length of message
        // (message size is limited to < 2^64 bits in this implementation)
        if (SHA_BlockSize::BLOCK_1024 == BLK) {
            buf.push64(0);
        }
        buf.push64(msgLengthBits);
    }

    static void padMessage(DataBufferStream& buf) {
        padMessage(*buf);
    }

    static bool padNeeded(const DataBuffer<ClearText>& buf) {
        // non-empty message must be even number of message input blocks
        return buf->empty() || 0 != buf->sizeBits() % blockSizeBits();
    }

    static bool padNeeded(DataBufferStream& buf) {
        return padNeeded(*buf);
    }

    // append (possibly lazy) word to message
    template <typename T>
    void msgInput(const T& a) {
        m_message.emplace_back(a);
    }

    // append array of words to message
    template <typename T, std::size_t N>
    void msgInput(const std::array<T, N>& a) {
        for (const auto& b : a)
            msgInput(b);
    }

    // append vector of words to message
    template <typename T>
    void msgInput(const std::vector<T>& a) {
        for (const auto& b : a)
            msgInput(b);
    }

    void clearMessage() {
        m_message.clear();
    }

    void computeHash() {
#ifdef USE_ASSERT
        assert(inputOK());
#endif

        auto* ptr = static_cast<CRTP*>(this);

        ptr->initHashValue();

        std::size_t msgIndex = 0;
        while (msgIndex < m_message.size()) {
            ptr->prepMsgSchedule(msgIndex);
            ptr->initWorkingVars();
            ptr->workingLoop();
            ptr->updateHash();
        }

        ptr->afterHash();
    }

protected:
    SHA_Base() = default;

    // note: reference not const so assignment can unbox laziness
    MSG& msgWord(std::size_t& index) {
        return m_message[index++];
    }

private:
    static std::size_t blockSizeBits() {
        switch (BLK) {
        case (SHA_BlockSize::BLOCK_512) : return 512;
        case (SHA_BlockSize::BLOCK_1024) : return 1024;
        }
    }

    static std::size_t wordSizeBits() {
        switch (BLK) {
        case (SHA_BlockSize::BLOCK_512) : return 32;
        case (SHA_BlockSize::BLOCK_1024) : return 64;
        }
    }

    bool inputOK() const {
        // non-empty message must be even number of message input blocks
        const std::size_t msgSizeBits = m_message.size() * wordSizeBits();
        return !m_message.empty() && 0 == msgSizeBits % blockSizeBits();
    }

    std::vector<MSG> m_message;
};

////////////////////////////////////////////////////////////////////////////////
// SHA common functions
//

template <typename T, typename U, typename BITWISE>
class SHA_Functions : public BITWISE
{
public:
    static U Ch(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_AND(x, y),
                BITWISE::_AND(BITWISE::_CMPLMNT(x), z));
    }

    static U Parity(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(x, y),
                z);
    }

    static U Maj(const T& x, const T& y, const T& z) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_AND(x, y),
                    BITWISE::_AND(x, z)),
                BITWISE::_AND(y, z));
    }

    static U f(const T& x, const T& y, const T& z, const std::size_t round) {
        if (round < 20) {
            return Ch(x, y, z);
        } else if (round < 40) {
            return Parity(x, y, z);
        } else if (round < 60) {
            return Maj(x, y, z);
        } else {
            return Parity(x, y, z);
        }
    }

    static U SIGMA_256_0(const T& x) { return SIGMA(x, 2, 13, 22); }
    static U SIGMA_256_1(const T& x) { return SIGMA(x, 6, 11, 25); }
    static U sigma_256_0(const T& x) { return sigma(x, 7, 18, 3); }
    static U sigma_256_1(const T& x) { return sigma(x, 17, 19, 10); }
    static U SIGMA_512_0(const T& x) { return SIGMA(x, 28, 34, 39); }
    static U SIGMA_512_1(const T& x) { return SIGMA(x, 14, 18, 41); }
    static U sigma_512_0(const T& x) { return sigma(x, 1, 8, 7); }
    static U sigma_512_1(const T& x) { return sigma(x, 19, 61, 6); }

private:
    static U SIGMA(const T& x,
                   const unsigned int a,
                   const unsigned int b,
                   const unsigned int c) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_ROTR(x, a),
                    BITWISE::_ROTR(x, b)),
                BITWISE::_ROTR(x, c));
    }

    static U sigma(const T& x,
                   const unsigned int a,
                   const unsigned int b,
                   const unsigned int c) {
        return
            BITWISE::XOR(
                BITWISE::_XOR(
                    BITWISE::_ROTR(x, a),
                    BITWISE::_ROTR(x, b)),
                BITWISE::_SHR(x, c));
    }
};

} // namespace snarkfront

#endif
<commit_msg>Delete SecureHashStd.hpp<commit_after><|endoftext|>


<commit_before>#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include <cassert>
#include <cmath>
#include <tr1/memory>

#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "verbose.h"
#include "hg.h"
#include "prob.h"
#include "inside_outside.h"
#include "ff_register.h"
#include "decoder.h"
#include "filelib.h"
#include "online_optimizer.h"
#include "fdict.h"
#include "weights.h"
#include "sparse_vector.h"
#include "sampler.h"

#ifdef HAVE_MPI
#include <boost/mpi/timer.hpp>
#include <boost/mpi.hpp>
namespace mpi = boost::mpi;
#endif

using namespace std;
namespace po = boost::program_options;

void SanityCheck(const vector<double>& w) {
  for (int i = 0; i < w.size(); ++i) {
    assert(!isnan(w[i]));
    assert(!isinf(w[i]));
  }
}

struct FComp {
  const vector<double>& w_;
  FComp(const vector<double>& w) : w_(w) {}
  bool operator()(int a, int b) const {
    return fabs(w_[a]) > fabs(w_[b]);
  }
};

void ShowLargestFeatures(const vector<double>& w) {
  vector<int> fnums(w.size());
  for (int i = 0; i < w.size(); ++i)
    fnums[i] = i;
  vector<int>::iterator mid = fnums.begin();
  mid += (w.size() > 10 ? 10 : w.size());
  partial_sort(fnums.begin(), mid, fnums.end(), FComp(w));
  cerr << "TOP FEATURES:";
  for (vector<int>::iterator i = fnums.begin(); i != mid; ++i) {
    cerr << ' ' << FD::Convert(*i) << '=' << w[*i];
  }
  cerr << endl;
}

bool InitCommandLine(int argc, char** argv, po::variables_map* conf) {
  po::options_description opts("Configuration options");
  opts.add_options()
        ("input_weights,w",po::value<string>(),"Input feature weights file")
        ("training_data,t",po::value<string>(),"Training data corpus")
        ("training_agenda,a",po::value<string>(), "Text file listing a series of configuration files and the number of iterations to train using each configuration successively")
        ("minibatch_size_per_proc,s", po::value<unsigned>()->default_value(5), "Number of training instances evaluated per processor in each minibatch")
        ("optimization_method,m", po::value<string>()->default_value("sgd"), "Optimization method (sgd)")
        ("random_seed,S", po::value<uint32_t>(), "Random seed (if not specified, /dev/random will be used)")
        ("eta_0,e", po::value<double>()->default_value(0.2), "Initial learning rate for SGD (eta_0)")
        ("L1,1","Use L1 regularization")
        ("regularization_strength,C", po::value<double>()->default_value(1.0), "Regularization strength (C)");
  po::options_description clo("Command line options");
  clo.add_options()
        ("config", po::value<string>(), "Configuration file")
        ("help,h", "Print this help message and exit");
  po::options_description dconfig_options, dcmdline_options;
  dconfig_options.add(opts);
  dcmdline_options.add(opts).add(clo);

  po::store(parse_command_line(argc, argv, dcmdline_options), *conf);
  if (conf->count("config")) {
    ifstream config((*conf)["config"].as<string>().c_str());
    po::store(po::parse_config_file(config, dconfig_options), *conf);
  }
  po::notify(*conf);

  if (conf->count("help") || !conf->count("training_data") || !conf->count("training_agenda")) {
    cerr << dcmdline_options << endl;
    return false;
  }
  return true;
}

void ReadTrainingCorpus(const string& fname, int rank, int size, vector<string>* c, vector<int>* order) {
  ReadFile rf(fname);
  istream& in = *rf.stream();
  string line;
  int id = 0;
  while(in) {
    getline(in, line);
    if (!in) break;
    if (id % size == rank) {
      c->push_back(line);
      order->push_back(id);
    }
    ++id;
  }
}

static const double kMINUS_EPSILON = -1e-6;

struct TrainingObserver : public DecoderObserver {
  void Reset() {
    acc_grad.clear();
    acc_obj = 0;
    total_complete = 0;
  }

  void SetLocalGradientAndObjective(vector<double>* g, double* o) const {
    *o = acc_obj;
    for (SparseVector<prob_t>::const_iterator it = acc_grad.begin(); it != acc_grad.end(); ++it)
      (*g)[it->first] = it->second;
  }

  virtual void NotifyDecodingStart(const SentenceMetadata& smeta) {
    cur_model_exp.clear();
    cur_obj = 0;
    state = 1;
  }

  // compute model expectations, denominator of objective
  virtual void NotifyTranslationForest(const SentenceMetadata& smeta, Hypergraph* hg) {
    assert(state == 1);
    state = 2;
    const prob_t z = InsideOutside<prob_t,
                                   EdgeProb,
                                   SparseVector<prob_t>,
                                   EdgeFeaturesAndProbWeightFunction>(*hg, &cur_model_exp);
    cur_obj = log(z);
    cur_model_exp /= z;
  }

  // compute "empirical" expectations, numerator of objective
  virtual void NotifyAlignmentForest(const SentenceMetadata& smeta, Hypergraph* hg) {
    assert(state == 2);
    state = 3;
    SparseVector<prob_t> ref_exp;
    const prob_t ref_z = InsideOutside<prob_t,
                                       EdgeProb,
                                       SparseVector<prob_t>,
                                       EdgeFeaturesAndProbWeightFunction>(*hg, &ref_exp);
    ref_exp /= ref_z;

    double log_ref_z;
#if 0
    if (crf_uniform_empirical) {
      log_ref_z = ref_exp.dot(feature_weights);
    } else {
      log_ref_z = log(ref_z);
    }
#else
    log_ref_z = log(ref_z);
#endif

    // rounding errors means that <0 is too strict
    if ((cur_obj - log_ref_z) < kMINUS_EPSILON) {
      cerr << "DIFF. ERR! log_model_z < log_ref_z: " << cur_obj << " " << log_ref_z << endl;
      exit(1);
    }
    assert(!isnan(log_ref_z));
    ref_exp -= cur_model_exp;
    acc_grad += ref_exp;
    acc_obj += (cur_obj - log_ref_z);
  }

  virtual void NotifyDecodingComplete(const SentenceMetadata& smeta) {
    if (state == 3) {
      ++total_complete;
    } else {
    }
  }

  void GetGradient(SparseVector<double>* g) const {
    g->clear();
    for (SparseVector<prob_t>::const_iterator it = acc_grad.begin(); it != acc_grad.end(); ++it)
      g->set_value(it->first, it->second);
  }

  int total_complete;
  SparseVector<prob_t> cur_model_exp;
  SparseVector<prob_t> acc_grad;
  double acc_obj;
  double cur_obj;
  int state;
};

#ifdef HAVE_MPI
namespace boost { namespace mpi {
  template<>
  struct is_commutative<std::plus<SparseVector<double> >, SparseVector<double> >
    : mpl::true_ { };
} } // end namespace boost::mpi
#endif

bool LoadAgenda(const string& file, vector<pair<string, int> >* a) {
  ReadFile rf(file);
  istream& in = *rf.stream();
  string line;
  while(in) {
    getline(in, line);
    if (!in) break;
    if (line.empty()) continue;
    if (line[0] == '#') continue;
    int sc = 0;
    if (line.size() < 3) return false;
    for (int i = 0; i < line.size(); ++i) { if (line[i] == ' ') ++sc; }
    if (sc != 1) { cerr << "Too many spaces in line: " << line << endl; return false; }
    size_t d = line.find(" ");
    pair<string, int> x;
    x.first = line.substr(0,d);
    x.second = atoi(line.substr(d+1).c_str());
    a->push_back(x);
    if (!FileExists(x.first)) {
      cerr << "Can't find file " << x.first << endl;
      return false;
    }
  }
  return true;
}

int main(int argc, char** argv) {
#ifdef HAVE_MPI
  mpi::environment env(argc, argv);
  mpi::communicator world;
  const int size = world.size();
  const int rank = world.rank();
#else
  const int size = 1;
  const int rank = 0;
#endif
  if (size > 1) SetSilent(true);  // turn off verbose decoder output
  register_feature_functions();
  std::tr1::shared_ptr<MT19937> rng;

  po::variables_map conf;
  if (!InitCommandLine(argc, argv, &conf))
    return 1;

  // load initial weights
  Weights weights;
  if (conf.count("input_weights"))
    weights.InitFromFile(conf["input_weights"].as<string>());

  vector<string> corpus;
  vector<int> ids;
  ReadTrainingCorpus(conf["training_data"].as<string>(), rank, size, &corpus, &ids);
  assert(corpus.size() > 0);

  std::tr1::shared_ptr<OnlineOptimizer> o;
  std::tr1::shared_ptr<LearningRateSchedule> lr;

  const unsigned size_per_proc = conf["minibatch_size_per_proc"].as<unsigned>();
  if (size_per_proc > corpus.size()) {
    cerr << "Minibatch size must be smaller than corpus size!\n";
    return 1;
  }

  size_t total_corpus_size = 0;
#ifdef HAVE_MPI
  reduce(world, corpus.size(), total_corpus_size, std::plus<size_t>(), 0);
#else
  total_corpus_size = corpus.size();
#endif

  if (rank == 0) {
    cerr << "Total corpus size: " << total_corpus_size << endl;
    const unsigned batch_size = size_per_proc * size;
    // TODO config
    lr.reset(new ExponentialDecayLearningRate(batch_size, conf["eta_0"].as<double>()));

    const string omethod = conf["optimization_method"].as<string>();
    if (omethod == "sgd") {
      const double C = conf["regularization_strength"].as<double>();
      o.reset(new CumulativeL1OnlineOptimizer(lr, total_corpus_size, C));
    } else {
      assert(!"fail");
    }
  }
  if (conf.count("random_seed"))
    rng.reset(new MT19937(conf["random_seed"].as<uint32_t>()));
  else
    rng.reset(new MT19937);

  SparseVector<double> x;
  weights.InitSparseVector(&x);
  TrainingObserver observer;

  int write_weights_every_ith = 100; // TODO configure
  int titer = -1;

  vector<pair<string, int> > agenda;
  if (!LoadAgenda(conf["training_agenda"].as<string>(), &agenda))
    return 1;
  if (rank == 0)
    cerr << "Loaded agenda defining " << agenda.size() << " training epochs\n";

  vector<double> lambdas;
  for (int ai = 0; ai < agenda.size(); ++ai) {
    const string& cur_config = agenda[ai].first;
    const unsigned max_iteration = agenda[ai].second;
    if (rank == 0)
      cerr << "STARTING TRAINING EPOCH " << (ai+1) << ". CONFIG=" << cur_config << endl;
    // load cdec.ini and set up decoder
    ReadFile ini_rf(cur_config);
    Decoder decoder(ini_rf.stream());

    if (rank == 0)
      o->ResetEpoch(); // resets the learning rate-- TODO is this good?

    int iter = -1;
    bool converged = false;
    while (!converged) {
#ifdef HAVE_MPI
      mpi::timer timer;
#endif
      weights.InitFromVector(x);
      weights.InitVector(&lambdas);
      ++iter; ++titer;
      observer.Reset();
      decoder.SetWeights(lambdas);
      if (rank == 0) {
        converged = (iter == max_iteration);
        SanityCheck(lambdas);
        ShowLargestFeatures(lambdas);
        string fname = "weights.cur.gz";
        if (iter % write_weights_every_ith == 0) {
          ostringstream o; o << "weights.epoch_" << (ai+1) << '.' << iter << ".gz";
          fname = o.str();
        }
        if (converged && ((ai+1)==agenda.size())) { fname = "weights.final.gz"; }
        ostringstream vv;
        vv << "total iter=" << titer << " (of current config iter=" << iter << ")  minibatch=" << size_per_proc << " sentences/proc x " << size << " procs.   num_feats=" << x.size() << '/' << FD::NumFeats() << "   passes_thru_data=" << (titer * size_per_proc / static_cast<double>(corpus.size())) << "   eta=" << lr->eta(titer);
        const string svv = vv.str();
        cerr << svv << endl;
        weights.WriteToFile(fname, true, &svv);
      }

      for (int i = 0; i < size_per_proc; ++i) {
        int ei = corpus.size() * rng->next();
        int id = ids[ei];
        decoder.SetId(id);
        decoder.Decode(corpus[ei], &observer);
      }
      SparseVector<double> local_grad, g;
      observer.GetGradient(&local_grad);
#ifdef HAVE_MPI
      reduce(world, local_grad, g, std::plus<SparseVector<double> >(), 0);
#else
      g.swap(local_grad);
#endif
      local_grad.clear();
      if (rank == 0) {
        g /= (size_per_proc * size);
        o->UpdateWeights(g, FD::NumFeats(), &x);
      }
#ifdef HAVE_MPI
      broadcast(world, x, 0);
      broadcast(world, converged, 0);
      world.barrier();
      if (rank == 0) { cerr << "  ELAPSED TIME THIS ITERATION=" << timer.elapsed() << endl; }
#endif
    }
  }
  return 0;
}
<commit_msg>enable weights to be frozen during training<commit_after>#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include <cassert>
#include <cmath>
#include <tr1/memory>

#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "verbose.h"
#include "hg.h"
#include "prob.h"
#include "inside_outside.h"
#include "ff_register.h"
#include "decoder.h"
#include "filelib.h"
#include "online_optimizer.h"
#include "fdict.h"
#include "weights.h"
#include "sparse_vector.h"
#include "sampler.h"

#ifdef HAVE_MPI
#include <boost/mpi/timer.hpp>
#include <boost/mpi.hpp>
namespace mpi = boost::mpi;
#endif

using namespace std;
namespace po = boost::program_options;

void SanityCheck(const vector<double>& w) {
  for (int i = 0; i < w.size(); ++i) {
    assert(!isnan(w[i]));
    assert(!isinf(w[i]));
  }
}

struct FComp {
  const vector<double>& w_;
  FComp(const vector<double>& w) : w_(w) {}
  bool operator()(int a, int b) const {
    return fabs(w_[a]) > fabs(w_[b]);
  }
};

void ShowLargestFeatures(const vector<double>& w) {
  vector<int> fnums(w.size());
  for (int i = 0; i < w.size(); ++i)
    fnums[i] = i;
  vector<int>::iterator mid = fnums.begin();
  mid += (w.size() > 10 ? 10 : w.size());
  partial_sort(fnums.begin(), mid, fnums.end(), FComp(w));
  cerr << "TOP FEATURES:";
  for (vector<int>::iterator i = fnums.begin(); i != mid; ++i) {
    cerr << ' ' << FD::Convert(*i) << '=' << w[*i];
  }
  cerr << endl;
}

bool InitCommandLine(int argc, char** argv, po::variables_map* conf) {
  po::options_description opts("Configuration options");
  opts.add_options()
        ("input_weights,w",po::value<string>(),"Input feature weights file")
        ("frozen_features,z",po::value<string>(), "List of features not to optimize")
        ("training_data,t",po::value<string>(),"Training data corpus")
        ("training_agenda,a",po::value<string>(), "Text file listing a series of configuration files and the number of iterations to train using each configuration successively")
        ("minibatch_size_per_proc,s", po::value<unsigned>()->default_value(5), "Number of training instances evaluated per processor in each minibatch")
        ("optimization_method,m", po::value<string>()->default_value("sgd"), "Optimization method (sgd)")
        ("random_seed,S", po::value<uint32_t>(), "Random seed (if not specified, /dev/random will be used)")
        ("eta_0,e", po::value<double>()->default_value(0.2), "Initial learning rate for SGD (eta_0)")
        ("L1,1","Use L1 regularization")
        ("regularization_strength,C", po::value<double>()->default_value(1.0), "Regularization strength (C)");
  po::options_description clo("Command line options");
  clo.add_options()
        ("config", po::value<string>(), "Configuration file")
        ("help,h", "Print this help message and exit");
  po::options_description dconfig_options, dcmdline_options;
  dconfig_options.add(opts);
  dcmdline_options.add(opts).add(clo);

  po::store(parse_command_line(argc, argv, dcmdline_options), *conf);
  if (conf->count("config")) {
    ifstream config((*conf)["config"].as<string>().c_str());
    po::store(po::parse_config_file(config, dconfig_options), *conf);
  }
  po::notify(*conf);

  if (conf->count("help") || !conf->count("training_data") || !conf->count("training_agenda")) {
    cerr << dcmdline_options << endl;
    return false;
  }
  return true;
}

void ReadTrainingCorpus(const string& fname, int rank, int size, vector<string>* c, vector<int>* order) {
  ReadFile rf(fname);
  istream& in = *rf.stream();
  string line;
  int id = 0;
  while(in) {
    getline(in, line);
    if (!in) break;
    if (id % size == rank) {
      c->push_back(line);
      order->push_back(id);
    }
    ++id;
  }
}

static const double kMINUS_EPSILON = -1e-6;

struct TrainingObserver : public DecoderObserver {
  void Reset() {
    acc_grad.clear();
    acc_obj = 0;
    total_complete = 0;
  }

  void SetLocalGradientAndObjective(vector<double>* g, double* o) const {
    *o = acc_obj;
    for (SparseVector<prob_t>::const_iterator it = acc_grad.begin(); it != acc_grad.end(); ++it)
      (*g)[it->first] = it->second;
  }

  virtual void NotifyDecodingStart(const SentenceMetadata& smeta) {
    cur_model_exp.clear();
    cur_obj = 0;
    state = 1;
  }

  // compute model expectations, denominator of objective
  virtual void NotifyTranslationForest(const SentenceMetadata& smeta, Hypergraph* hg) {
    assert(state == 1);
    state = 2;
    const prob_t z = InsideOutside<prob_t,
                                   EdgeProb,
                                   SparseVector<prob_t>,
                                   EdgeFeaturesAndProbWeightFunction>(*hg, &cur_model_exp);
    cur_obj = log(z);
    cur_model_exp /= z;
  }

  // compute "empirical" expectations, numerator of objective
  virtual void NotifyAlignmentForest(const SentenceMetadata& smeta, Hypergraph* hg) {
    assert(state == 2);
    state = 3;
    SparseVector<prob_t> ref_exp;
    const prob_t ref_z = InsideOutside<prob_t,
                                       EdgeProb,
                                       SparseVector<prob_t>,
                                       EdgeFeaturesAndProbWeightFunction>(*hg, &ref_exp);
    ref_exp /= ref_z;

    double log_ref_z;
#if 0
    if (crf_uniform_empirical) {
      log_ref_z = ref_exp.dot(feature_weights);
    } else {
      log_ref_z = log(ref_z);
    }
#else
    log_ref_z = log(ref_z);
#endif

    // rounding errors means that <0 is too strict
    if ((cur_obj - log_ref_z) < kMINUS_EPSILON) {
      cerr << "DIFF. ERR! log_model_z < log_ref_z: " << cur_obj << " " << log_ref_z << endl;
      exit(1);
    }
    assert(!isnan(log_ref_z));
    ref_exp -= cur_model_exp;
    acc_grad += ref_exp;
    acc_obj += (cur_obj - log_ref_z);
  }

  virtual void NotifyDecodingComplete(const SentenceMetadata& smeta) {
    if (state == 3) {
      ++total_complete;
    } else {
    }
  }

  void GetGradient(SparseVector<double>* g) const {
    g->clear();
    for (SparseVector<prob_t>::const_iterator it = acc_grad.begin(); it != acc_grad.end(); ++it)
      g->set_value(it->first, it->second);
  }

  int total_complete;
  SparseVector<prob_t> cur_model_exp;
  SparseVector<prob_t> acc_grad;
  double acc_obj;
  double cur_obj;
  int state;
};

#ifdef HAVE_MPI
namespace boost { namespace mpi {
  template<>
  struct is_commutative<std::plus<SparseVector<double> >, SparseVector<double> >
    : mpl::true_ { };
} } // end namespace boost::mpi
#endif

bool LoadAgenda(const string& file, vector<pair<string, int> >* a) {
  ReadFile rf(file);
  istream& in = *rf.stream();
  string line;
  while(in) {
    getline(in, line);
    if (!in) break;
    if (line.empty()) continue;
    if (line[0] == '#') continue;
    int sc = 0;
    if (line.size() < 3) return false;
    for (int i = 0; i < line.size(); ++i) { if (line[i] == ' ') ++sc; }
    if (sc != 1) { cerr << "Too many spaces in line: " << line << endl; return false; }
    size_t d = line.find(" ");
    pair<string, int> x;
    x.first = line.substr(0,d);
    x.second = atoi(line.substr(d+1).c_str());
    a->push_back(x);
    if (!FileExists(x.first)) {
      cerr << "Can't find file " << x.first << endl;
      return false;
    }
  }
  return true;
}

int main(int argc, char** argv) {
#ifdef HAVE_MPI
  mpi::environment env(argc, argv);
  mpi::communicator world;
  const int size = world.size();
  const int rank = world.rank();
#else
  const int size = 1;
  const int rank = 0;
#endif
  if (size > 1) SetSilent(true);  // turn off verbose decoder output
  register_feature_functions();
  std::tr1::shared_ptr<MT19937> rng;

  po::variables_map conf;
  if (!InitCommandLine(argc, argv, &conf))
    return 1;

  // load initial weights
  Weights weights;
  if (conf.count("input_weights"))
    weights.InitFromFile(conf["input_weights"].as<string>());

  vector<int> frozen_fids;
  if (conf.count("frozen_features")) {
    ReadFile rf(conf["frozen_features"].as<string>());
    istream& in = *rf.stream();
    string line;
    while(in) {
      getline(in, line);
      if (line.empty()) continue;
      if (line[0] == ' ' || line[line.size() - 1] == ' ') { line = Trim(line); }
      frozen_fids.push_back(FD::Convert(line));
    }
    if (rank == 0) cerr << "Freezing " << frozen_fids.size() << " features.\n";
  }

  vector<string> corpus;
  vector<int> ids;
  ReadTrainingCorpus(conf["training_data"].as<string>(), rank, size, &corpus, &ids);
  assert(corpus.size() > 0);

  std::tr1::shared_ptr<OnlineOptimizer> o;
  std::tr1::shared_ptr<LearningRateSchedule> lr;

  const unsigned size_per_proc = conf["minibatch_size_per_proc"].as<unsigned>();
  if (size_per_proc > corpus.size()) {
    cerr << "Minibatch size must be smaller than corpus size!\n";
    return 1;
  }

  size_t total_corpus_size = 0;
#ifdef HAVE_MPI
  reduce(world, corpus.size(), total_corpus_size, std::plus<size_t>(), 0);
#else
  total_corpus_size = corpus.size();
#endif

  if (rank == 0) {
    cerr << "Total corpus size: " << total_corpus_size << endl;
    const unsigned batch_size = size_per_proc * size;
    // TODO config
    lr.reset(new ExponentialDecayLearningRate(batch_size, conf["eta_0"].as<double>()));

    const string omethod = conf["optimization_method"].as<string>();
    if (omethod == "sgd") {
      const double C = conf["regularization_strength"].as<double>();
      o.reset(new CumulativeL1OnlineOptimizer(lr, total_corpus_size, C));
    } else {
      assert(!"fail");
    }
  }
  if (conf.count("random_seed"))
    rng.reset(new MT19937(conf["random_seed"].as<uint32_t>()));
  else
    rng.reset(new MT19937);

  SparseVector<double> x;
  weights.InitSparseVector(&x);
  TrainingObserver observer;

  int write_weights_every_ith = 100; // TODO configure
  int titer = -1;

  vector<pair<string, int> > agenda;
  if (!LoadAgenda(conf["training_agenda"].as<string>(), &agenda))
    return 1;
  if (rank == 0)
    cerr << "Loaded agenda defining " << agenda.size() << " training epochs\n";

  vector<double> lambdas;
  for (int ai = 0; ai < agenda.size(); ++ai) {
    const string& cur_config = agenda[ai].first;
    const unsigned max_iteration = agenda[ai].second;
    if (rank == 0)
      cerr << "STARTING TRAINING EPOCH " << (ai+1) << ". CONFIG=" << cur_config << endl;
    // load cdec.ini and set up decoder
    ReadFile ini_rf(cur_config);
    Decoder decoder(ini_rf.stream());

    if (rank == 0)
      o->ResetEpoch(); // resets the learning rate-- TODO is this good?

    int iter = -1;
    bool converged = false;
    while (!converged) {
#ifdef HAVE_MPI
      mpi::timer timer;
#endif
      weights.InitFromVector(x);
      weights.InitVector(&lambdas);
      ++iter; ++titer;
      observer.Reset();
      decoder.SetWeights(lambdas);
      if (rank == 0) {
        converged = (iter == max_iteration);
        SanityCheck(lambdas);
        ShowLargestFeatures(lambdas);
        string fname = "weights.cur.gz";
        if (iter % write_weights_every_ith == 0) {
          ostringstream o; o << "weights.epoch_" << (ai+1) << '.' << iter << ".gz";
          fname = o.str();
        }
        if (converged && ((ai+1)==agenda.size())) { fname = "weights.final.gz"; }
        ostringstream vv;
        vv << "total iter=" << titer << " (of current config iter=" << iter << ")  minibatch=" << size_per_proc << " sentences/proc x " << size << " procs.   num_feats=" << x.size() << '/' << FD::NumFeats() << "   passes_thru_data=" << (titer * size_per_proc / static_cast<double>(corpus.size())) << "   eta=" << lr->eta(titer);
        const string svv = vv.str();
        cerr << svv << endl;
        weights.WriteToFile(fname, true, &svv);
      }

      for (int i = 0; i < size_per_proc; ++i) {
        int ei = corpus.size() * rng->next();
        int id = ids[ei];
        decoder.SetId(id);
        decoder.Decode(corpus[ei], &observer);
      }
      SparseVector<double> local_grad, g;
      observer.GetGradient(&local_grad);
#ifdef HAVE_MPI
      reduce(world, local_grad, g, std::plus<SparseVector<double> >(), 0);
#else
      g.swap(local_grad);
#endif
      local_grad.clear();
      for (int i = 0; i < frozen_fids.size(); ++i)
        g.erase(frozen_fids[i]);
      if (rank == 0) {
        g /= (size_per_proc * size);
        o->UpdateWeights(g, FD::NumFeats(), &x);
      }
#ifdef HAVE_MPI
      broadcast(world, x, 0);
      broadcast(world, converged, 0);
      world.barrier();
      if (rank == 0) { cerr << "  ELAPSED TIME THIS ITERATION=" << timer.elapsed() << endl; }
#endif
    }
  }
  return 0;
}
<|endoftext|>


<commit_before>// bslmt_latch.cpp                                                    -*-C++-*-
#include <bslmt_latch.h>

#include <bsls_ident.h>
BSLS_IDENT_RCSID(bslmt_latch_cpp,"$Id$ $CSID$")

#include <bslmt_barrier.h>        // for testing only
#include <bslmt_lockguard.h>
#include <bslmt_threadgroup.h>    // for testing only
#include <bslmt_threadutil.h>     // for testing only

namespace BloombergLP {
namespace bslmt {

                             // -----------
                             // class Latch
                             // -----------

// CREATORS
Latch::~Latch()
{
}

// MANIPULATORS
void Latch::arrive()
{
    countDown(1);
}

void Latch::arriveAndWait()
{
    countDown(1);
    wait();
}

void Latch::countDown(int numEvents)
{
    BSLS_ASSERT(numEvents  > 0);
    BSLS_ASSERT(d_sigCount >= numEvents);

    // Point 1: The following operation requires release semantics to ensure
    // memory visibility for other threads using 'currentCount' and 'tryWait'
    // (see Points 2 and 3 below, respectively).

    if (0 == d_sigCount.addAcqRel(-numEvents)) {
        LockGuard<Mutex> lock(&d_mutex);

        d_cond.broadcast();
    }
}

void Latch::wait()
{
    LockGuard<Mutex> lock(&d_mutex);

    // Note that the following operation does not require memory visibility
    // guarantees because they are already provided by the lock/unlock of
    // 'd_mutex'.

    while (d_sigCount.loadRelaxed() > 0) {
        d_cond.wait(&d_mutex);
    }
}

// ACCESSORS
int Latch::currentCount() const
{
    // Point 2: The following operation requires acquire semantics to ensure
    // memory visibility for other threads using 'countDown' (see Point 1
    // above).  Note that while this method is not intended for
    // synchronization, clients may still use it in that way.

    return d_sigCount.loadAcquire();
}

bool Latch::tryWait() const
{
    // Point 3: The following operation requires acquire semantics to ensure
    // memory visibility for other threads using 'countDown' (see Point 1
    // above).

    return 0 == d_sigCount.loadAcquire();
}

}  // close package namespace
}  // close enterprise namespace

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
<commit_msg>apply fix (from David S.) for race (which apparently affects OS X only)<commit_after>// bslmt_latch.cpp                                                    -*-C++-*-
#include <bslmt_latch.h>

#include <bsls_ident.h>
BSLS_IDENT_RCSID(bslmt_latch_cpp,"$Id$ $CSID$")

#include <bslmt_barrier.h>        // for testing only
#include <bslmt_lockguard.h>
#include <bslmt_threadgroup.h>    // for testing only
#include <bslmt_threadutil.h>     // for testing only

namespace BloombergLP {
namespace bslmt {

                             // -----------
                             // class Latch
                             // -----------

// CREATORS
Latch::~Latch()
{
}

// MANIPULATORS
void Latch::arrive()
{
    countDown(1);
}

void Latch::arriveAndWait()
{
    countDown(1);
    wait();
}

void Latch::countDown(int numEvents)
{
    BSLS_ASSERT(numEvents > 0);

    // Point 1: The following operation requires release semantics to ensure
    // memory visibility for other threads using 'currentCount' and 'tryWait'
    // (see Points 2 and 3 below, respectively).

    do {
        int current  = d_sigCount.loadRelaxed();
        int expected = current - numEvents;
        BSLS_ASSERT(0 <= expected);

        if (0 == expected) {
            // 0 is a special case: by contract, only 1 thread can ever believe
            // it is about to decrement the count to 0 (because if there were
            // two threads in that situation, one of them would take the count
            // to 0 and then the other would illegally make the count
            // negative).  Thus, we can simply save a 0 under the lock,
            // broadcast on the condition variable, and exit the function.
            //
            // We want to save the 0 under the lock because in typical usage,
            // the waiting thread owns this structure and may destroy it once
            // it observes a 0.

            LockGuard<Mutex> lock(&d_mutex);

            d_sigCount.storeRelease(0);
            d_cond.broadcast();

            return;                                                   // RETURN
        }
    } while (current != d_sigCount.testAndSwapAcqRel(current, expected));
}

void Latch::wait()
{
    LockGuard<Mutex> lock(&d_mutex);

    // Note that the following operation does not require memory visibility
    // guarantees because they are already provided by the lock/unlock of
    // 'd_mutex'.

    while (d_sigCount.loadRelaxed() > 0) {
        d_cond.wait(&d_mutex);
    }
}

// ACCESSORS
int Latch::currentCount() const
{
    // Point 2: The following operation requires acquire semantics to ensure
    // memory visibility for other threads using 'countDown' (see Point 1
    // above).  Note that while this method is not intended for
    // synchronization, clients may still use it in that way.

    return d_sigCount.loadAcquire();
}

bool Latch::tryWait() const
{
    // Point 3: The following operation requires acquire semantics to ensure
    // memory visibility for other threads using 'countDown' (see Point 1
    // above).

    return 0 == d_sigCount.loadAcquire();
}

}  // close package namespace
}  // close enterprise namespace

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: collelem.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 21:31:53 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SAMPLE_COLLELEM_HXX
#define _SAMPLE_COLLELEM_HXX

#ifndef _SBX_SBXOBJECT_HXX //autogen
#include <sbxobj.hxx>
#endif

// Das Sample-Element ist ein kleines Objekt, das die Properties
// Name und Value enthlt sowie die Methode Say, die den bergebenen
// Text mit dem eigenen Namen verkoppelt. Der Name ist von aussen setzbar.
// Die Implementation arbeitet ausschliesslich mit dynamischen Elementen.

class SampleElement : public SbxObject
{
    // Broadcaster Notification
    virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
                             const SfxHint& rHint, const TypeId& rHintType );
public:
    SampleElement( const String& );
};

#endif
<commit_msg>INTEGRATION: CWS ab17fixes (1.2.8); FILE MERGED<commit_after>/*************************************************************************
 *
 *  $RCSfile: collelem.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2005-09-29 12:57:09 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SAMPLE_COLLELEM_HXX
#define _SAMPLE_COLLELEM_HXX

#ifndef _SBX_SBXOBJECT_HXX //autogen
#include <sbxobj.hxx>
#endif

// Das Sample-Element ist ein kleines Objekt, das die Properties
// Name und Value enthlt sowie die Methode Say, die den bergebenen
// Text mit dem eigenen Namen verkoppelt. Der Name ist von aussen setzbar.
// Die Implementation arbeitet ausschliesslich mit dynamischen Elementen.

class SampleElement : public SbxObject
{
    // Broadcaster Notification
    virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
                             const SfxHint& rHint, const TypeId& rHintType );
public:
    SampleElement( const String& );
};

#endif
<|endoftext|>


<commit_before>#ifndef CINSERT_ITERATOR
#define CINSERT_ITERATOR
#include<iterator>
#include<memory>	//addressof
#include<utility>	//move

namespace nTool
{
	template<class T,class Hold,class RefFunc,class MoveFunc>
	class CInsert_iterator:public std::iterator<std::output_iterator_tag,void,void,void,void>
	{
		Hold *hold_;
		MoveFunc move_;
		RefFunc ref_;
	public:
		typedef T value_type;
		CInsert_iterator(Hold &hold,const RefFunc ref) noexcept
			:CInsert_iterator{hold,ref,ref}{}
		CInsert_iterator(Hold &hold,const RefFunc ref,const MoveFunc move) noexcept
			:hold_{std::addressof(hold)},move_{move},ref_{ref}{}
		inline CInsert_iterator& operator*() noexcept
		{
			return *this;
		}
		inline CInsert_iterator& operator++() noexcept
		{
			return *this;
		}
		inline CInsert_iterator& operator++(int) noexcept
		{
			return *this;
		}
		CInsert_iterator& operator=(const value_type &val)
		{
			(hold_->*ref_)(val);
			return *this;
		}
		CInsert_iterator& operator=(value_type &&rVal)
		{
			(hold_->*move_)(std::move(rVal));
			return *this;
		}
	};

	template<class T,class Hold,class RefFunc,class MoveFunc>
	inline CInsert_iterator<T,Hold,RefFunc,MoveFunc> inserter(Hold &hold,const RefFunc ref,const MoveFunc move)
	{
		return CInsert_iterator<T,Hold,RefFunc,MoveFunc>(hold,ref,move);
	}

	template<class T,class Hold,class RefFunc>
	inline CInsert_iterator<T,Hold,RefFunc,RefFunc> inserter(Hold &hold,const RefFunc ref)
	{
		return inserter<T>(hold,ref,ref);
	}
}

#endif<commit_msg>add const to parameter, rename variable<commit_after>#ifndef CINSERT_ITERATOR
#define CINSERT_ITERATOR
#include<iterator>
#include<memory>	//addressof
#include<utility>	//move

namespace nTool
{
	template<class T,class Hold,class RefFunc,class MoveFunc>
	class CInsert_iterator:public std::iterator<std::output_iterator_tag,void,void,void,void>
	{
		Hold *hold_;
		MoveFunc move_;
		RefFunc ref_;
	public:
		typedef T value_type;
		CInsert_iterator(Hold &hold,const RefFunc ref) noexcept
			:CInsert_iterator{hold,ref,ref}{}
		CInsert_iterator(Hold &hold,const RefFunc ref,const MoveFunc move) noexcept
			:hold_{std::addressof(hold)},move_{move},ref_{ref}{}
		inline CInsert_iterator& operator*() noexcept
		{
			return *this;
		}
		inline CInsert_iterator& operator++() noexcept
		{
			return *this;
		}
		inline CInsert_iterator& operator++(const int) noexcept
		{
			return *this;
		}
		CInsert_iterator& operator=(const value_type &val)
		{
			(hold_->*ref_)(val);
			return *this;
		}
		CInsert_iterator& operator=(value_type &&xval)
		{
			(hold_->*move_)(std::move(xval));
			return *this;
		}
	};

	template<class T,class Hold,class RefFunc,class MoveFunc>
	inline CInsert_iterator<T,Hold,RefFunc,MoveFunc> inserter(Hold &hold,const RefFunc ref,const MoveFunc move)
	{
		return CInsert_iterator<T,Hold,RefFunc,MoveFunc>(hold,ref,move);
	}

	template<class T,class Hold,class RefFunc>
	inline CInsert_iterator<T,Hold,RefFunc,RefFunc> inserter(Hold &hold,const RefFunc ref)
	{
		return inserter<T>(hold,ref,ref);
	}
}

#endif<|endoftext|>


<commit_before>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
// vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/* Copyright (c) FFLAS-FFPACK
* Written by Clément Pernet <clement.pernet@imag.fr>
* ========LICENCE========
* This file is part of the library FFLAS-FFPACK.
*
* FFLAS-FFPACK is free software: you can redistribute it and/or modify
* it under the terms of the  GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
* ========LICENCE========
*/

#ifndef __FFLASFFPACK_HAVE_DGETRF
#define __FFLASFFPACK_HAVE_DGETRF 1
#endif
#include "fflas-ffpack/fflas-ffpack-config.h"

#include <iostream>
#include <vector>
#include <givaro/modular.h>

#include "fflas-ffpack/fflas-ffpack.h"
#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/utils/fflas_io.h"
#include "fflas-ffpack/utils/args-parser.h"

using namespace std;

#ifdef __FFLASFFPACK_USE_OPENMP
typedef FFLAS::OMPTimer TTimer;
#else
typedef FFLAS::Timer TTimer;
#endif

#define EFFGFF(n,t,i) ( (double(n)/1000.*double(n)/1000.*double(n)/1000.0) / double(t) * double(i) / 3.)

int main(int argc, char** argv) {

	size_t iter = 3;
	int    q    = 1009;
	int    algo = 1;
	size_t    n    = 2000;
	std::string file = "";

	size_t NBK = MAX_THREADS;

	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic (-1 for random).",  TYPE_INT , &q },
		{ 'n', "-n N", "Set the dimension of the matrix.",               TYPE_INT , &n },
		{ 'i', "-i R", "Set number of repetitions.",                     TYPE_INT , &iter },
		{ 'f', "-f FILE", "Set the input file (empty for random).",  TYPE_STR , &file },
		{ 'a', "-a Algorithm", "Set the algorithm (0 for default, 1 for Aasen, 2 for rook, 3 for rk.",  TYPE_INT , &algo },
		END_OF_ARGUMENTS
	};

	FFLAS::parseArguments(argc,argv,as);

    typedef Givaro::Modular<double> Field;
    typedef Field::Element Element;

    Field F(q);
    Field::Element * A;

    TTimer chrono;
    double *time=new double[iter];

    std::vector<int> Piv(n,0);
    std::vector<double> Diag(n,0.0);
    for (size_t it=0;it <= iter;++it){
        if (!file.empty()){
            FFLAS::ReadMatrix (file.c_str(),F,n,n,A);
        }
        else {
            A = FFLAS::fflas_new<Element>(n*n);
            Field::RandIter G(F);
            PAR_BLOCK{ FFLAS::pfrand(F,G,n,n,A,n/NBK); }
        }

        chrono.clear();
        switch(algo) {
            case 0:
                if (it) chrono.start();
                LAPACKE_dsytrf(101,'U',n,A,n,&Piv[0]);
                if (it) chrono.stop();
                break;
            case 1:
                if (it) chrono.start();
                LAPACKE_dsytrf_aa(101,'U',n,A,n,&Piv[0]);
                if (it) chrono.stop();
                break;
            case 2:
                if (it) chrono.start();
                LAPACKE_dsytrf_rook(101,'U',n,A,n,&Piv[0]);
                if (it) chrono.stop();
                break;
            default:
                if (it) chrono.start();
                LAPACKE_dsytrf_rk(101,'U',n,A,n,&Diag[0],&Piv[0]);
                if (it) chrono.stop();
        }
        if (it) time[it-1] = chrono.realtime();
        FFLAS::fflas_delete( A);
    }

    std::sort(time, time+iter);
    double mediantime = time[iter/2];
    delete[] time;

        // -----------
        // Standard output for benchmark - Alexis Breust 2014/11/14
    switch(algo) {
        case 0:
            std::cout << "DSYTRFtime: ";
            break;
        case 1:
            std::cout << "DSYTRFAAtime: ";
            break;
        case 2:
            std::cout << "DSYTRFROOKtime: ";
            break;
        default:
            std::cout << "DSYTRFRKtime: ";
    }

    std::cout << mediantime
              << " Gfops: " << EFFGFF(n,mediantime,1);
    FFLAS::writeCommandString(std::cout, as) << std::endl;

    return 0;
}

<commit_msg>disable bench-dsytrf by default until we autotest availability of the LAPACKE routines<commit_after>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
// vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/* Copyright (c) FFLAS-FFPACK
* Written by Clément Pernet <clement.pernet@imag.fr>
* ========LICENCE========
* This file is part of the library FFLAS-FFPACK.
*
* FFLAS-FFPACK is free software: you can redistribute it and/or modify
* it under the terms of the  GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
* ========LICENCE========
*/

// For the moment, please manually uncomment these defines when your BLAS provide these symbols (waiting to autodect them in a near future)
// #define __FFLASFFPACK_HAVE_LAPACK2_DSYTRF
// #define __FFLASFFPACK_HAVE_LAPACK2_DSYTRF_AA
// #define __FFLASFFPACK_HAVE_LAPACK2_DSYTRF_ROOK
// #define __FFLASFFPACK_HAVE_LAPACK2_DSYTRF_RK

#include "fflas-ffpack/fflas-ffpack-config.h"

#include <iostream>
#include <vector>
#include <givaro/modular.h>

#include "fflas-ffpack/fflas-ffpack.h"
#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/utils/fflas_io.h"
#include "fflas-ffpack/utils/args-parser.h"

using namespace std;

#ifdef __FFLASFFPACK_USE_OPENMP
typedef FFLAS::OMPTimer TTimer;
#else
typedef FFLAS::Timer TTimer;
#endif

#define EFFGFF(n,t,i) ( (double(n)/1000.*double(n)/1000.*double(n)/1000.0) / double(t) * double(i) / 3.)

int main(int argc, char** argv) {

	size_t iter = 3;
	int    q    = 1009;
	int    algo = 1;
	size_t    n    = 2000;
	std::string file = "";

	size_t NBK = MAX_THREADS;

	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic (-1 for random).",  TYPE_INT , &q },
		{ 'n', "-n N", "Set the dimension of the matrix.",               TYPE_INT , &n },
		{ 'i', "-i R", "Set number of repetitions.",                     TYPE_INT , &iter },
		{ 'f', "-f FILE", "Set the input file (empty for random).",  TYPE_STR , &file },
		{ 'a', "-a Algorithm", "Set the algorithm (0 for default, 1 for Aasen, 2 for rook, 3 for rk.",  TYPE_INT , &algo },
		END_OF_ARGUMENTS
	};

	FFLAS::parseArguments(argc,argv,as);

    typedef Givaro::Modular<double> Field;
    typedef Field::Element Element;

    Field F(q);
    Field::Element * A;

    TTimer chrono;
    double *time=new double[iter];

    std::vector<int> Piv(n,0);
    std::vector<double> Diag(n,0.0);
    for (size_t it=0;it <= iter;++it){
        if (!file.empty()){
            FFLAS::ReadMatrix (file.c_str(),F,n,n,A);
        }
        else {
            A = FFLAS::fflas_new<Element>(n*n);
            Field::RandIter G(F);
            PAR_BLOCK{ FFLAS::pfrand(F,G,n,n,A,n/NBK); }
        }

        chrono.clear();
        switch(algo) {
            case 0:
                if (it) chrono.start();
#ifdef __FFLASFFPACK_HAVE_LAPACK2_DSYTRF
                LAPACKE_dsytrf(101,'U',n,A,n,&Piv[0]);
#endif
                if (it) chrono.stop();
                break;
            case 1:
                if (it) chrono.start();
#ifdef __FFLASFFPACK_HAVE_LAPACK2_DSYTRF_AA
                LAPACKE_dsytrf_aa(101,'U',n,A,n,&Piv[0]);
#endif
                if (it) chrono.stop();
                break;
            case 2:
                if (it) chrono.start();
#ifdef __FFLASFFPACK_HAVE_LAPACK2_DSYTRF_ROOK
                LAPACKE_dsytrf_rook(101,'U',n,A,n,&Piv[0]);
#endif
                if (it) chrono.stop();
                break;
            default:
                if (it) chrono.start();
#ifdef __FFLASFFPACK_HAVE_LAPACK2_DSYTRF_RK
                LAPACKE_dsytrf_rk(101,'U',n,A,n,&Diag[0],&Piv[0]);
#endif
                if (it) chrono.stop();
        }
        if (it) time[it-1] = chrono.realtime();
        FFLAS::fflas_delete( A);
    }

    std::sort(time, time+iter);
    double mediantime = time[iter/2];
    delete[] time;

        // -----------
        // Standard output for benchmark - Alexis Breust 2014/11/14
    switch(algo) {
        case 0:
            std::cout << "DSYTRFtime: ";
            break;
        case 1:
            std::cout << "DSYTRFAAtime: ";
            break;
        case 2:
            std::cout << "DSYTRFROOKtime: ";
            break;
        default:
            std::cout << "DSYTRFRKtime: ";
    }

    std::cout << mediantime
              << " Gfops: " << EFFGFF(n,mediantime,1);
    FFLAS::writeCommandString(std::cout, as) << std::endl;

    return 0;
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "input.h"

#include "asdf_multiplat/main/mouse.h"

#include "editor.h"

namespace asdf
{
    using namespace input;

namespace hexmap
{
namespace editor
{

    input_handler_t::input_handler_t(editor_t& _editor)
    : input::hex_map_input_t(_editor.hex_map.get(), _editor.hex_map->camera)
    , editor(_editor)
    {
    }

    bool input_handler_t::on_event(SDL_Event* event)
    {
        input::hex_map_input_t::on_event(event);

        //TODO: only check/do this during certain sdl events
        if(mouse_input->mouse_button_state(mouse_left))
        {
            auto mw = world_coords();
            auto hx = hex_coords_from_mouse(mouse_input->mouse_position);

            LOG("mw: %.2f, %.2f   hx: %i, %i", mw.x, mw.y, hx.x, hx.y);

            if(hex_map->hex_grid.is_in_bounds(hx))
            {
                auto& cell = hex_map->hex_grid.cell_at(hx);
                cell.tile_id = current_tile_id;
                return true;
            }
        }

        switch(event->type)
        {
            case SDL_KEYDOWN:
                on_key_down(event->key.keysym.sym);
                break;
        }

        return false;
    }

    void input_handler_t::on_key_down(SDL_Keycode key)
    {
        switch(key)
        {
            case SDLK_1: current_tile_id = 1; break;
            case SDLK_2: current_tile_id = 2; break;
            case SDLK_3: current_tile_id = 3; break;
            case SDLK_4: current_tile_id = 4; break;
            case SDLK_5: current_tile_id = 5; break;
            case SDLK_6: current_tile_id = 6; break;
            case SDLK_7: current_tile_id = 7; break;
            case SDLK_8: current_tile_id = 8; break;
            case SDLK_9: current_tile_id = 9; break;
            case SDLK_0: current_tile_id = 0; break;

            case SDLK_KP_1: current_object_id = 1; break;
            case SDLK_KP_2: current_object_id = 2; break;
            case SDLK_KP_3: current_object_id = 3; break;
            case SDLK_KP_4: current_object_id = 4; break;
            case SDLK_KP_5: current_object_id = 5; break;
            case SDLK_KP_6: current_object_id = 6; break;
            case SDLK_KP_7: current_object_id = 7; break;
            case SDLK_KP_8: current_object_id = 8; break;
            case SDLK_KP_9: current_object_id = 9; break;
            case SDLK_KP_0: current_object_id = 0; break;

            case SDLK_KP_PERIOD: current_object_id = -1; break;

            case sdl2_input_map[cancel_action]:
                //TODO
                break;

            case sdl2_input_map[set_tool_select]:
                editor.set_tool(editor_t::select);
                break;
            case set_tool_terrain_paint:
                editor.set_tool(editor_t::terrain_paint);
                break;
            case set_tool_place_object:
                editor.set_tool(editor_t::place_object);
                break;
            case set_tool_place_spline:
                editor.set_tool(editor_t::place_spline);
                break;

        }

        //LOG("%i", key);
    }

}
}
}<commit_msg>minor fix<commit_after>#include "stdafx.h"
#include "input.h"

#include "asdf_multiplat/main/mouse.h"

#include "editor.h"

namespace asdf
{
    using namespace input;

namespace hexmap
{
namespace editor
{

    input_handler_t::input_handler_t(editor_t& _editor)
    : input::hex_map_input_t(_editor.hex_map.get(), _editor.hex_map->camera)
    , editor(_editor)
    {
    }

    bool input_handler_t::on_event(SDL_Event* event)
    {
        input::hex_map_input_t::on_event(event);

        //TODO: only check/do this during certain sdl events
        if(mouse_input->mouse_button_state(mouse_left))
        {
            auto mw = world_coords();
            auto hx = hex_coords_from_mouse(mouse_input->mouse_position);

            LOG("mw: %.2f, %.2f   hx: %i, %i", mw.x, mw.y, hx.x, hx.y);

            if(hex_map->hex_grid.is_in_bounds(hx))
            {
                auto& cell = hex_map->hex_grid.cell_at(hx);
                cell.tile_id = current_tile_id;
                return true;
            }
        }

        switch(event->type)
        {
            case SDL_KEYDOWN:
                on_key_down(event->key.keysym.sym);
                break;
        }

        return false;
    }

    void input_handler_t::on_key_down(SDL_Keycode key)
    {
        switch(key)
        {
            case SDLK_1: current_tile_id = 1; break;
            case SDLK_2: current_tile_id = 2; break;
            case SDLK_3: current_tile_id = 3; break;
            case SDLK_4: current_tile_id = 4; break;
            case SDLK_5: current_tile_id = 5; break;
            case SDLK_6: current_tile_id = 6; break;
            case SDLK_7: current_tile_id = 7; break;
            case SDLK_8: current_tile_id = 8; break;
            case SDLK_9: current_tile_id = 9; break;
            case SDLK_0: current_tile_id = 0; break;

            case SDLK_KP_1: current_object_id = 1; break;
            case SDLK_KP_2: current_object_id = 2; break;
            case SDLK_KP_3: current_object_id = 3; break;
            case SDLK_KP_4: current_object_id = 4; break;
            case SDLK_KP_5: current_object_id = 5; break;
            case SDLK_KP_6: current_object_id = 6; break;
            case SDLK_KP_7: current_object_id = 7; break;
            case SDLK_KP_8: current_object_id = 8; break;
            case SDLK_KP_9: current_object_id = 9; break;
            case SDLK_KP_0: current_object_id = 0; break;

            case SDLK_KP_PERIOD: current_object_id = -1; break;

            case sdl2_input_map[cancel_action]:
                //TODO
                break;

            case sdl2_input_map[set_tool_select]:
                editor.set_tool(editor_t::select);
                break;
            case sdl2_input_map[set_tool_terrain_paint]:
                editor.set_tool(editor_t::terrain_paint);
                break;
            case sdl2_input_map[set_tool_place_object]:
                editor.set_tool(editor_t::place_object);
                break;
            case sdl2_input_map[set_tool_place_spline]:
                editor.set_tool(editor_t::place_spline);
                break;

        }

        //LOG("%i", key);
    }

}
}
}<|endoftext|>