Skip to content

Commit

Permalink
split ParserGridDistribution into hpp/cpp file
Browse files Browse the repository at this point in the history
fix ComputationalRadiationPhysics#2898

Split the grid parser into a interface file `hpp` and the implementation `cpp` to avoid that boost regex is parsed by nvcc.
Boost regex is very often the root of compile issues because nvcc is not able to split the host and device part correctly.

Split `ParserGridDistribution` to avoid t
  • Loading branch information
psychocoderHPC committed Feb 19, 2019
1 parent 6a70750 commit 9fefecd
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 103 deletions.
142 changes: 142 additions & 0 deletions include/picongpu/initialization/ParserGridDistribution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/* Copyright 2013-2019 Axel Huebl, Rene Widera, Benjamin Worpitz
*
* This file is part of PIConGPU.
*
* PIConGPU is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PIConGPU is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PIConGPU.
* If not, see <http://www.gnu.org/licenses/>.
*/

#include "picongpu/initialization/ParserGridDistribution.hpp"

#include <pmacc/verify.hpp>
#include <cstdint>
#include <vector> // std::vector
#include <string> // std::string
#include <iterator> // std::distance

#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>


namespace picongpu
{

ParserGridDistribution::ParserGridDistribution( std::string const s )
{
parsedInput = parse( s );
}

uint32_t
ParserGridDistribution::getOffset( uint32_t const devicePos, uint32_t const maxCells ) const
{
value_type::const_iterator iter = parsedInput.begin();
// go to last device of these n subdomains extent{n}
uint32_t i = iter->count - 1u;
uint32_t sum = 0u;

while( i < devicePos )
{
// add last subdomain
sum += iter->extent * iter->count;

++iter;
// go to last device of these n subdomains extent{n}
i += iter->count;
}

// add part of this subdomain that is before me
sum += iter->extent * ( devicePos + iter->count - i - 1u );

// check total number of cells
uint32_t sumTotal = 0u;
for( iter = parsedInput.begin(); iter != parsedInput.end(); ++iter )
sumTotal += iter->extent * iter->count;

PMACC_VERIFY( sumTotal == maxCells );

return sum;
}

uint32_t
ParserGridDistribution::getLocalSize( uint32_t const devicePos ) const
{
value_type::const_iterator iter = parsedInput.begin();
// go to last device of these n subdomains extent{n}
uint32_t i = iter->count - 1u;

while( i < devicePos )
{
++iter;
// go to last device of these n subdomains extent{n}
i += iter->count;
}

return iter->extent;
}

void
ParserGridDistribution::verifyDevices( uint32_t const numDevices ) const
{
uint32_t numSubdomains = 0u;
for( SubdomainPair const & p : parsedInput )
numSubdomains += p.count;

PMACC_VERIFY( numSubdomains == numDevices );
}

ParserGridDistribution::value_type
ParserGridDistribution::parse( std::string const s ) const
{
boost::regex regFind( "[0-9]+(\\{[0-9]+\\})*",
boost::regex_constants::perl );

boost::sregex_token_iterator iter( s.begin( ), s.end( ),
regFind, 0 );
boost::sregex_token_iterator end;

value_type newInput;
newInput.reserve( std::distance( iter, end ) );

for(; iter != end; ++iter )
{
std::string pM = *iter;

// find count n and extent b of b{n}
boost::regex regCount(
"(.*\\{)|(\\})",
boost::regex_constants::perl
);
std::string count = boost::regex_replace( pM, regCount, "" );

boost::regex regExtent(
"\\{.*\\}",
boost::regex_constants::perl
);
std::string extent = boost::regex_replace( pM, regExtent, "" );

// no count {n} given (implies one)
if( count == *iter )
count = "1";

const SubdomainPair g = {
boost::lexical_cast< uint32_t > ( extent ),
boost::lexical_cast< uint32_t > ( count )
};
newInput.emplace_back( g );
}

return newInput;
}

} // namespace picongpu
109 changes: 6 additions & 103 deletions include/picongpu/initialization/ParserGridDistribution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,9 @@

#pragma once

#include <pmacc/verify.hpp>
#include <vector> // std::vector
#include <string> // std::string
#include <iterator> // std::distance

#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
#include <cstdint>


namespace picongpu
Expand All @@ -52,63 +48,18 @@ class ParserGridDistribution
using value_type = std::vector< SubdomainPair >;

public:
ParserGridDistribution( std::string const s )
{
parsedInput = parse( s );
}
ParserGridDistribution( std::string const s );

uint32_t
getOffset( uint32_t const devicePos, uint32_t const maxCells ) const
{
value_type::const_iterator iter = parsedInput.begin();
// go to last device of these n subdomains extent{n}
uint32_t i = iter->count - 1u;
uint32_t sum = 0u;

while( i < devicePos )
{
// add last subdomain
sum += iter->extent * iter->count;

++iter;
// go to last device of these n subdomains extent{n}
i += iter->count;
}

// add part of this subdomain that is before me
sum += iter->extent * ( devicePos + iter->count - i - 1u );

// check total number of cells
uint32_t sumTotal = 0u;
for( iter = parsedInput.begin(); iter != parsedInput.end(); ++iter )
sumTotal += iter->extent * iter->count;

PMACC_VERIFY( sumTotal == maxCells );

return sum;
}
getOffset( uint32_t const devicePos, uint32_t const maxCells ) const;

/** Get local Size of this dimension
*
* \param[in] devicePos as unsigned integer in the range [0, n-1] for this dimension
* \return uint32_t with local number of cells
*/
uint32_t
getLocalSize( uint32_t const devicePos ) const
{
value_type::const_iterator iter = parsedInput.begin();
// go to last device of these n subdomains extent{n}
uint32_t i = iter->count - 1u;

while( i < devicePos )
{
++iter;
// go to last device of these n subdomains extent{n}
i += iter->count;
}

return iter->extent;
}
getLocalSize( uint32_t const devicePos ) const;

/** Verify the number of subdomains matches the devices
*
Expand All @@ -118,14 +69,7 @@ class ParserGridDistribution
* \param[in] numDevices number of devices for this dimension
*/
void
verifyDevices( uint32_t const numDevices ) const
{
uint32_t numSubdomains = 0u;
for( SubdomainPair const & p : parsedInput )
numSubdomains += p.count;

PMACC_VERIFY( numSubdomains == numDevices );
}
verifyDevices( uint32_t const numDevices ) const;

private:
value_type parsedInput;
Expand All @@ -140,48 +84,7 @@ class ParserGridDistribution
* \return std::vector<SubdomainPair> with 2x uint32_t (extent, count)
*/
value_type
parse( std::string const s ) const
{
boost::regex regFind( "[0-9]+(\\{[0-9]+\\})*",
boost::regex_constants::perl );

boost::sregex_token_iterator iter( s.begin( ), s.end( ),
regFind, 0 );
boost::sregex_token_iterator end;

value_type newInput;
newInput.reserve( std::distance( iter, end ) );

for(; iter != end; ++iter )
{
std::string pM = *iter;

// find count n and extent b of b{n}
boost::regex regCount(
"(.*\\{)|(\\})",
boost::regex_constants::perl
);
std::string count = boost::regex_replace( pM, regCount, "" );

boost::regex regExtent(
"\\{.*\\}",
boost::regex_constants::perl
);
std::string extent = boost::regex_replace( pM, regExtent, "" );

// no count {n} given (implies one)
if( count == *iter )
count = "1";

const SubdomainPair g = {
boost::lexical_cast< uint32_t > ( extent ),
boost::lexical_cast< uint32_t > ( count )
};
newInput.emplace_back( g );
}

return newInput;
}
parse( std::string const s ) const;

};

Expand Down

0 comments on commit 9fefecd

Please sign in to comment.