Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ ASCII数据导入:如何匹配Fortran';在C+中的大容量读取性能+;? 设置_C++_Fortran_Ascii - Fatal编程技术网

C++ ASCII数据导入:如何匹配Fortran';在C+中的大容量读取性能+;? 设置

C++ ASCII数据导入:如何匹配Fortran';在C+中的大容量读取性能+;? 设置,c++,fortran,ascii,C++,Fortran,Ascii,您好,我有用于读取ASCII双精度数据的Fortran代码(问题底部的数据文件示例): 和“等效”C++代码: #include <fstream> #include <vector> using std::ifstream; using std::vector; using std::ios; int main(){ int mx, my, mz; // Open the file 'CHGCAR' ifstream InFile('CHG

您好,我有用于读取ASCII双精度数据的Fortran代码(问题底部的数据文件示例):

和“等效”C++代码:

#include <fstream>
#include <vector>

using std::ifstream;
using std::vector;
using std::ios;

int main(){
    int mx, my, mz;

    // Open the file 'CHGCAR'
    ifstream InFile('CHGCAR', ios::in);

    // Get the extent of the 3D system and allocate the 3D array
    InFile >> mx >> my >> mz;
    vector<vector<vector<double> > > charge(mx, vector<vector<double> >(my, vector<double>(mz)));

    // Method 1: std::ifstream extraction operator to double
    for (int i = 0; i < mx; ++i)
        for (int j = 0; j < my; ++j)
            for (int k = 0; k < mz; ++k)
                InFile >> charge[i][j][k];

    return 0;
}
for (int i = 0; i < mx; ++i)
    for (int j = 0; j < my; ++j)
        for (int k = 0; k < mz; ++k)
            InFile >> charge[i][j][k];

执行与C++代码相同的任务:

#include <fstream>
#include <vector>

using std::ifstream;
using std::vector;
using std::ios;

int main(){
    int mx, my, mz;

    // Open the file 'CHGCAR'
    ifstream InFile('CHGCAR', ios::in);

    // Get the extent of the 3D system and allocate the 3D array
    InFile >> mx >> my >> mz;
    vector<vector<vector<double> > > charge(mx, vector<vector<double> >(my, vector<double>(mz)));

    // Method 1: std::ifstream extraction operator to double
    for (int i = 0; i < mx; ++i)
        for (int j = 0; j < my; ++j)
            for (int k = 0; k < mz; ++k)
                InFile >> charge[i][j][k];

    return 0;
}
for (int i = 0; i < mx; ++i)
    for (int j = 0; j < my; ++j)
        for (int k = 0; k < mz; ++k)
            InFile >> charge[i][j][k];
同样,这比简单的基于操作符的方法要快得多,但仍然比Fortran版本慢得多——更不用说更多的代码了

如何获得更好的性能? 我确信,如果我要自己实现方法2,那么方法2就是一条路,但我很好奇如何提高性能以匹配Fortran代码。我正在考虑和正在研究的事情有:

  • C++11和C++14特性
  • 优化C或C++库,只做这种类型的事情
  • 对方法2中使用的各个方法的改进
    • 标记化库,例如,而不是
      strtok()
    • atof()
C++字符串工具包

特别是C++字符串工具包库将采用<代码>文件> <代码>和分隔符>代码> \n”/代码>并给我一个字符串标记对象(调用它<代码>文件> /CODE >,那么<<代码>循环的三进制代码>看起来像

for (int k = 0; k < Mz; ++k)
    for (int j = 0; j < My; ++j)
        for (int i = 0; i < Mx; ++i)
            Charge[k][j][i] = FileTokens.nextFloatToken();
StrTk示例 下面是上面提到的。该场景正在解析包含3D网格信息的数据文件:

输入数据:

5
+1.0,+1.0,+1.0
-1.0,+1.0,-1.0
-1.0,-1.0,+1.0
+1.0,-1.0,-1.0
+0.0,+0.0,+0.0
4
0,1,4
1,2,4
2,3,4
3,1,4
代码:

结构点
{
双x,y,z;
};
结构三角形
{
标准:尺寸为i0、i1、i2;
};
int main()
{
std::string mesh_file=“mesh.txt”;
std::ifstream流(mesh_file.c_str());
std::字符串s;
//工艺点组
标准::德克点;
p点;
标准::大小\u t点\u计数=0;
strtk::解析线(流,“,点计数);
strtk::对于每条线(流,
点数,
[&点,&p](常量标准::字符串和行)
{
if(strtk::parse(第,,,行,p.x,p.y,p.z))
点。推回(p);
});
//处理三角形部分
三角形;
三角形t;
标准::大小\u t三角形\u计数=0;
strtk::解析线(流,“,三角形计数);
strtk::对于每条线(流,
三角计数,
[&三角形,&t](常量标准::字符串和线)
{
if(strtk::parse(行,,,t.i0,t.i1,t.i2))
三角形。推回(t);
});
返回0;
}

vector<vector<vector<double> > > charge(mx, vector<vector<double> >(my, vector<double>(mz)));
如果你的乐观主义者做得很好,这应该不会有什么帮助,但作为一种理智的检查,值得一试

如果你仍然比较慢,或者只是想尝试更快,你可以尝试优化你的数字解析:你说你的数据的格式都是ala
0.23080516813E+04
——固定大小,你可以很容易地计算出要读入缓冲区的字节数,以便从内存中获得适当数量的值,然后你可以为每一个字节计算一个字节在
之后启动一个
atol
以提取23080516813,然后将其乘以10的负幂(11(您的位数)减去04):为了提高速度,保留一个10的幂的表格,并使用提取的指数(即4)对其进行索引。(注意:在许多常见硬件上,乘以1E-7可能比除以1E7快。)

如果你想闪电式地解决这个问题,就改用内存映射文件访问。值得考虑的是,它比POSIX API(更不用说Windows)更容易使用,而且是可移植的,但是直接针对OS API编程也不难

更新-对第一和第二条评论的回应 使用boost内存映射的示例:

#include <boost/iostreams/device/mapped_file.hpp>

boost::mapped_file_params params("dbldat.in");
boost::mapped_file_source file(params);
file.open();
ASSERT(file.is_open());
const char* p = file.data();
const char* nl = strchr(p, '\n');
std::istringstream iss(std::string(p, nl - p));
size_t x, y, z;
ASSERT(iss >> x >> y >> z);
#包括
boost::mapped_file_params params(“dbldat.in”);
boost::映射的_文件_源文件(params);
file.open();
断言(file.is_open());
const char*p=file.data();
常量char*nl=strchr(p,'\n');
std::istringstream-iss(std::string(p,nl-p));
尺寸x,y,z;
断言(iss>>x>>y>>z);
上面将一个文件映射到地址
p
的内存中,然后从第一行解析维度。从
++nl
开始继续解析实际的
表示。我在上面提到了一种方法,您关心的是数据格式的更改:您可以在文件中添加一个版本号,所以您可以使用优化解析,直到版本号更改,然后对“未知”文件格式采用通用的方式。就通用的方式而言,对于使用
int chars_to_skip;double my_double;ASSERT的内存表示(sscanf(ptr),%f%n,&my_double,&chars_to_skip)=1)
是合理的:请参阅-然后可以通过
字符到跳过
将指针推进数据

接下来,您是否建议将
reserve()
解决方案与引用创建解决方案相结合

还有(请原谅我的无知)为什么使用
charge[i][j]
v.emplace\u back()
要比
charge[i][j].emplace\u back()好

这个建议是为了检查编译器是否没有对每个放置的元素重复计算
charge[i][j]
:希望这不会对性能造成影响,您可以返回
charge[i][j].emplace()
,但我认为这值得快速检查

最后,我对在每个循环的顶部使用空向量和reserve()表示怀疑。我有另一个程序使用该方法突然停止,用预先分配的多维向量替换reserve()大大加快了速度

这是可能的,但在一般情况下不一定是正确的,也不一定适用于这里——这在很大程度上取决于编译器/optimi
struct point
{
   double x,y,z;
};

struct triangle
{
   std::size_t i0,i1,i2;
};

int main()
{
   std::string mesh_file = "mesh.txt";
   std::ifstream stream(mesh_file.c_str());
   std::string s;
   // Process points section
   std::deque<point> points;
   point p;
   std::size_t point_count = 0;
   strtk::parse_line(stream," ",point_count);
   strtk::for_each_line_n(stream,
                          point_count,
                          [&points,&p](const std::string& line)
                          {
                             if (strtk::parse(line,",",p.x,p.y,p.z))
                                points.push_back(p);
                          });

   // Process triangles section
   std::deque<triangle> triangles;
   triangle t;
   std::size_t triangle_count = 0;
   strtk::parse_line(stream," ",triangle_count);
   strtk::for_each_line_n(stream,
                          triangle_count,
                          [&triangles,&t](const std::string& line)
                          {
                             if (strtk::parse(line,",",t.i0,t.i1,t.i2))
                                triangles.push_back(t);
                          });
   return 0;
}
vector<vector<vector<double> > > charge(mx, vector<vector<double> >(my, vector<double>(mz)));
for (int i = 0; i < mx; ++i)
    for (int j = 0; j < my; ++j)
    {
        std::vector<double>& v = charge[i][j];
        for (int k = 0; k < mz; ++k)
        {
            double d;
            InFile >> d;
            v.emplace_pack(d);
        }
    }
#include <boost/iostreams/device/mapped_file.hpp>

boost::mapped_file_params params("dbldat.in");
boost::mapped_file_source file(params);
file.open();
ASSERT(file.is_open());
const char* p = file.data();
const char* nl = strchr(p, '\n');
std::istringstream iss(std::string(p, nl - p));
size_t x, y, z;
ASSERT(iss >> x >> y >> z);