Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/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
如何使用QTextStream优化ASCII输出_Qt_Optimization_Qt4 - Fatal编程技术网

如何使用QTextStream优化ASCII输出

如何使用QTextStream优化ASCII输出,qt,optimization,qt4,Qt,Optimization,Qt4,我目前正在将数十亿个二进制记录写入ASCII文件(ugh)。我的工作还不错,但如果可以的话,我想优化性能。问题是,用户可以选择任意数量的字段来输出,所以我无法在编译时知道它们将包含3-12个字段中的哪一个 有没有更快的方法来构造ASCII文本行?正如您所看到的,字段的类型变化很大,我想不出绕过if()语句系列的方法。输出ASCII文件每记录一行,因此我尝试使用用arg构建的模板,但这只会使速度降低15% 更快的解决方案不必使用QTextStream,也不必直接写入文件,但输出太大,无法将整个内容

我目前正在将数十亿个二进制记录写入ASCII文件(ugh)。我的工作还不错,但如果可以的话,我想优化性能。问题是,用户可以选择任意数量的字段来输出,所以我无法在编译时知道它们将包含3-12个字段中的哪一个

有没有更快的方法来构造ASCII文本行?正如您所看到的,字段的类型变化很大,我想不出绕过if()语句系列的方法。输出ASCII文件每记录一行,因此我尝试使用用arg构建的模板,但这只会使速度降低15%

更快的解决方案不必使用QTextStream,也不必直接写入文件,但输出太大,无法将整个内容写入内存

下面是一些示例代码:

QFile outfile(outpath);
if(!outfile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
{
    qWarning("Could not open ASCII for writing!");
    return false;
} else
{
    /* compute XYZ precision */
    int prec[3] = {0, 0, 0}; //these non-zero values are determined programmatically

    /* set up the writer */
    QTextStream out(&outfile);
    out.setRealNumberNotation(QTextStream::FixedNotation);
    out.setRealNumberPrecision(3);
    QString del(config.delimiter); //the user chooses the delimiter character (comma, tab, etc) - using QChar is slower since it has to be promoted to QString anyway

    /* write the header line */
    out << "X" << del << "Y" << del << "Z";
    if(config.fields & INTFIELD)
        out << del << "IntegerField";
    if(config.fields & DBLFIELD)
        out << del << "DoubleField";
    if(config.fields & INTFIELD2)
        out << del << "IntegerField2";
    if(config.fields & TRIPLEFIELD)
        out << del << "Tri1" << del << "Tri2" << del << "Tri3";
    out << "\n";

    /* write out the points */
    for(quint64 ptnum = 0; ptnum < numpoints; ++ptnum)
    {
        pt = points.at(ptnum);
        out.setRealNumberPrecision(prec[0]);
        out << pt->getXYZ(0);
        out.setRealNumberPrecision(prec[1]);
        out << del << pt->getXYZ(1);
        out.setRealNumberPrecision(prec[2]);
        out << del << pt->getXYZ(2);
        out.setRealNumberPrecision(3);
        if(config.fields & INTFIELD)
            out << del << pt->getIntValue();
        if(config.fields & DBLFIELD)
            out << del << pt->getDoubleValue();
        if(config.fields & INTFIELD2)
            out << del << pt->getIntValue2();
        if(config.fields & TRIPLEFIELD)
        {
            out << del << pt->getTriple(0);
            out << del << pt->getTriple(1);
            out << del << pt->getTriple(2);
        }
        out << "\n";
    } //end for every point
outfile.close();
QFile输出文件(输出路径);
如果(!outfile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
{
qWarning(“无法打开ASCII进行写入!”);
返回false;
}否则
{
/*计算XYZ精度*/
int prec[3]={0,0,0};//这些非零值是通过编程确定的
/*设置作者*/
QTextStream out(&outfile);
out.setRealNumberNotation(QTextStream::FixedNotation);
out.setRealNumberPrecision(3);
QString del(config.delimiter);//用户选择分隔符字符(逗号、制表符等)-使用QChar速度较慢,因为它必须升级为QString
/*写标题行*/
out(这不会回答探查器的问题。它会尝试回答原始问题,即性能问题。)

在这种情况下,我建议完全避免使用QTextStream,看看这是否有帮助。它可能有助于提高性能的原因是它涉及到开销,因为文本是用于存储的,然后在写入时再次解码为ASCII或UTF-8。您有两个不需要的转换

尝试只使用标准的C++ >代码> STD::OSTRIGSWORDS类,它与QTrimeScript非常相似,只需要在代码中进行微小的更改。例如:

#include <sstream>

// ...

QFile outfile(outpath);
if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text
                | QIODevice::Truncate))
{
    qWarning("Could not open ASCII for writing!");
    return false;
}

/* compute XYZ precision */
int prec[3] = {0, 0, 0};

std::ostringstream out;
out.precision(3);
std::fixed(out);
// I assume config.delimiter is a QChar.
char del = config.delimiter.toLatin1();

/* write the header line */
out << "X" << del << "Y" << del << "Z";
if(config.fields & INTFIELD)
    out << del << "IntegerField";
if(config.fields & DBLFIELD)
    out << del << "DoubleField";
if(config.fields & INTFIELD2)
    out << del << "IntegerField2";

if(config.fields & TRIPLEFIELD)
    out << del << "Tri1" << del << "Tri2" << del << "Tri3";
out << "\n";

/* write out the points */
for(quint64 ptnum = 0; ptnum < numpoints; ++ptnum)
{
    pt = points.at(ptnum);
    out.precision(prec[0]);
    out << pt->getXYZ(0);
    out.precision(prec[1]);
    out << del << pt->getXYZ(1);
    out.precision(prec[2]);
    out << del << pt->getXYZ(2);
    out.precision(3);
    if(config.fields & INTFIELD)
        out << del << pt->getIntValue();
    if(config.fields & DBLFIELD)
        out << del << pt->getDoubleValue();
    if(config.fields & INTFIELD2)
        out << del << pt->getIntValue2();
    if(config.fields & TRIPLEFIELD)
    {
        out << del << pt->getTriple(0);
        out << del << pt->getTriple(1);
        out << del << pt->getTriple(2);
    }
    out << "\n";

    // Write out the data and empty the stream.
    outfile.write(out.str().data(), out.str().length());
    out.str("");
}
outfile.close();
#包括
// ...
QFile outfile(输出路径);
如果(!outfile.open)(QIODevice::WriteOnly | QIODevice::Text
|QIODevice::截断)
{
qWarning(“无法打开ASCII进行写入!”);
返回false;
}
/*计算XYZ精度*/
int prec[3]={0,0,0};
std::ostringstream out;
精度(3);
标准::固定(输出);
//我假设config.delimiter是一个QChar。
char del=config.delimiter.toLatin1();
/*写标题行*/

OUT

假定你正在编写数十亿条记录,你可以考虑使用Boost <代码>噶玛< /Cord>库:

根据它们的基准,它运行速度远远超过C++流,甚至SaveTf与大多数编译器/库,包括Visual C++ 2010:


这需要一些学习,但您将获得显著的加速。

如果您没有合适的探查器,但有一个允许您中断正在运行的应用程序的调试器,则可以选择手动探查: -在调试器中启动应用程序,调用慢代码部分 -执行慢部分时随机中断执行 -查看调用堆栈并注意哪个子例程处于活动状态 -重复几次(大约10倍左右)


现在很有可能在大多数情况下都发现了相同的过程-这是一个你必须避免/加快的过程,以改进事情

这里我使用标准C库重写了你的代码-可能更快。我没有测试,所以你可能需要阅读一些fprintf格式规范文档n-根据编译器的不同,格式标志可能不同

注意getTriple()函数的返回类型-如果不是float,则必须更改前面格式规范中的%f

#include <stdio.h>

FILE* out;

out = fopen(outpath, "w");
if (out == NULL)
{
    qWarning("Could not open ASCII for writing!");
    return false;
} else {
    /* compute XYZ precision */
    int prec[3] = {0, 0, 0}; //these non-zero values are determined programmatically

    /* set up the writer */
    char del = config.delimiter;

    char s[255];        // or more if needed..
    /* write the header line */
    sprintf(s, "X%cY%cZ%c", del, del, del);
    fputs(s, out);
    if(config.fields & INTFIELD)
        fputs("IntegerField", out);
    if(config.fields & DBLFIELD)
        fputs("DoubleField", out);
    if(config.fields & INTFIELD2)
        fputs("IntegerField2", out);
    if(config.fields & TRIPLEFIELD) {
        sprintf(s, "%cTri1%cTri2%cTri3", del, del, del);
        fputs(s, out);
    }
    fputs("\n", out);

    /* write out the points */
    for(quint64 ptnum = 0; ptnum < numpoints; ++ptnum)
    {
        pt = points.at(ptnum);
        sprintf(s, "%.*f%c%.*f%c%.*f%c", prec[0], pt->getXYZ(0), del, prec[1], pt->getXYZ(1), del, prec[2], pt->getXYZ(2), del);
        fputs(s, out);            
        if(config.fields & INTFIELD)
            sprintf(s, "%d", pt->getIntValue());
        if(config.fields & DBLFIELD)
            sprintf(s, "%f", pt->getDoubleValue());
        if(config.fields & INTFIELD2)
            sprintf(s, "%d", pt->getIntValue2());
        fputs(s, out);
        if(config.fields & TRIPLEFIELD)
        {
            sprintf(s, "%c%f%c%f%c%f", del, pt->getTriple(0), del, pt->getTriple(1), del, pt->getTriple(2));    // assuming the getTriples() return double - need to adjust the %f to the real type
            fputs(s, out);
        }
        fputs("\n", out);
    } //end for every point
    fclose(out);
}
#包括
归档;
out=fopen(输出路径,“w”);
if(out==NULL)
{
qWarning(“无法打开ASCII进行写入!”);
返回false;
}否则{
/*计算XYZ精度*/
int prec[3]={0,0,0};//这些非零值是通过编程确定的
/*设置作者*/
char del=config.delimiter;
char s[255];//如果需要,可以使用更多字符。。
/*写标题行*/
sprintf(s,“X%cY%cZ%c”,del,del,del);
FPUT(s,out);
if(config.fields和INTFIELD)
fputs(“IntegerField”,out);
if(config.fields和DBLFIELD)
FPUT(“双场”,输出);
if(config.fields和INTFIELD2)
fputs(“IntegerField2”,out);
if(config.fields和TRIPLEFIELD){
sprintf,“%cTri1%cTri2%cTri3”,del,del,del);
FPUT(s,out);
}
FPUT(“\n”,out);
/*写出要点*/
对于(quint64 ptnum=0;ptnumgetXYZ(0),del,prec[1],pt->getXYZ(1),del,prec[2],pt->getXYZ(2),del);
FPUT(s,out);
if(config.fields和INTFIELD)
sprintf,“%d”,pt->getIntValue();
if(config.fields和DBLFIELD)
sprintf,“%f”,pt->getDoubleValue());
if(config.fields和INTFIELD2)
sprintf,“%d”,pt->getIntValue2();
FPUT(s,out);
if(config.fields和TRIPLEFIELD)
{
sprintf,“%c%f%c%f%c%f”,del,pt->getTriple(0),del,pt->getTriple(1),del,pt->getTriple(2));//假设getTriple()返回double-需要将%f调整为实际类型
FPUT(s,out);
}
FPUT(“\n”,out);
}//每点结束
fclose(out);
}
使用多核(如果可用)! 在我看来,数据的每个点都是独立的。 因此,您可以使用QtConcurrent::mappedReduced拆分预处理。 e、 g:

  • 将数据分为一系列块,每个块由N(例如1000)个点组成
  • 那就让你的
    void saveData(const QString & filename, const QVector<double> & iVect){
       QFile file(filename);
       if( !file.open(QIODevice::WriteOnly) )
          return;
       QDataStream out(file);
       for(int i=0;i<iVect.count();i++){
          out << iVect[i];
       file.close();
    }