HDFql从std :: vector迭代填充数据集

时间:2019-09-09 07:53:24

标签: hdf5 hdf hdfql

我正在尝试使用HDFql反复将数据集填充到HDF5文件中。我的意思是,迭代器偶尔会附带更新,我希望将更多数据(包含在std::vector中)转储到我的数据集中。奇怪的是,经过几次“迭代”后,某些东西中断了,我的数据集开始只填充零。

幸运的是,在一个最小的示例中也发生了此错误,并且似乎可以通过以下代码重现:

#include <stdio.h>
#include <random>
#include <HDFql.hpp>

int main (int argc, const char * argv[]) {
    HDFql::execute("CREATE TRUNCATE FILE /tmp/test_random.h5");
    HDFql::execute("USE FILE /tmp/test_random.h5");
    HDFql::execute("CREATE GROUP data");
    HDFql::execute("CREATE CHUNKED DATASET data/vals AS SMALLINT(UNLIMITED)");
    HDFql::execute("CLOSE FILE");
    std::stringstream ss;
    std::random_device rd;
    std::mt19937 eng(rd());
    std::uniform_int_distribution<> dist_vals(0, 500);
    std::uniform_int_distribution<> dist_len(300, 1000);
    for(int i=0; i<500; i++)
    {
        const int num_values = dist_len(eng);
        std::vector<uint16_t> vals;
        for(int i=0; i<num_values; i++)
        {
            const int value = dist_vals(eng);
            vals.push_back(value);
        }
        HDFql::execute("USE FILE /tmp/test_random.h5");

        ss << "ALTER DIMENSION data/vals TO +" << vals.size();
        HDFql::execute(ss.str().c_str()); ss.str("");

        ss << "INSERT INTO data/vals(-" << vals.size() << ":1:1:" << vals.size() 
            << ") VALUES FROM MEMORY " 
            << HDFql::variableTransientRegister(vals.data());
        HDFql::execute(ss.str().c_str()); ss.str("");

        HDFql::execute("CLOSE FILE");
    }
}

此代码运行500次“迭代”,每次用随机数量的随机数据填充数据向量。在我的最新运行中,最终输出hdf文件中数据单元4065之外的所有内容都为零。

所以我的问题是:我在这里做错了什么? 非常感谢!

编辑

在进一步的实验中,我得出的结论是,这可能是HDFql中的错误。看下面的例子:

#include <stdio.h>
#include <random>
#include <HDFql.hpp>

int main (int argc, const char * argv[]) {
    HDFql::execute("CREATE TRUNCATE FILE /tmp/test_random.h5");
    HDFql::execute("USE FILE /tmp/test_random.h5");
    HDFql::execute("CREATE CHUNKED DATASET data/vals AS SMALLINT(0 TO UNLIMITED)");

    std::stringstream ss;
    std::random_device rd;
    std::mt19937 eng(rd());
    std::uniform_int_distribution<> dist_vals(0, 450);
    std::uniform_int_distribution<> dist_len(100, 300);
    int total_added = 0;

    for(int i=0; i<5000; i++)
    {
        const int num_values = 1024; //dist_len(eng);
        std::vector<uint16_t> vals;
        for(int j=0; j<num_values; j++)
        {
            const int value = dist_vals(eng);
            vals.push_back(value);
        }

        long long dim=0;
        ss << "SHOW DIMENSION data/vals INTO MEMORY " << HDFql::variableTransientRegister(&dim);
        HDFql::execute(ss.str().c_str()); ss.str("");

        ss << "ALTER DIMENSION data/vals TO +" << vals.size();
        HDFql::execute(ss.str().c_str()); ss.str("");

        ss << "INSERT INTO data/vals(-" << vals.size() << ":1:1:" << vals.size()
            << ") VALUES FROM MEMORY "
            << HDFql::variableTransientRegister(vals.data());
        HDFql::execute(ss.str().c_str()); ss.str("");

        total_added += vals.size();
        std::cout << i << ": "<<  ss.str() << ":  dim = " << dim
                << " : added = " << vals.size() << " (total="
                << total_added << ")" << std::endl;

    }

    HDFql::execute("CLOSE FILE");
}

此代码将数据大小保持恒定为1024(num_values = 1024;),并且应该可以正常工作。但是,如果将其更改为1025,则会出现该错误,并通过控制台输出证明该错误:

....
235: :  dim = 240875 : added = 1025 (total=241900)
236: :  dim = 241900 : added = 1025 (total=242925)
237: :  dim = 0 : added = 1025 (total=243950)
238: :  dim = 0 : added = 1025 (total=244975)
239: :  dim = 0 : added = 1025 (total=246000)
....

由于数据集的维数显然不为零,因此表明在迭代470处发生了某些事情。

奇怪的是,这不能解释为什么在原始示例中出现此问题,因为数据数组的大小限制为500。

3 个答案:

答案 0 :(得分:1)

在外部i和内部for循环中都使用变量data,这是错误的。另外,建议您使用以下方法对您发布的代码段进行优化:

  1. 无需创建组data/vals,就像创建数据集data一样,HDFql会创建vals作为组(如果不存在)和{{1} }作为数据集。

  2. 无需在循环内打开和关闭文件/tmp/test_random.h5(因为这会降低性能);只需在代码开头打开文件,然后在代码末尾关闭文件即可。

此处是已更正/重构的代码:

#include <stdio.h>
#include <random>
#include <HDFql.hpp>

int main (int argc, const char * argv[]) {

    HDFql::execute("CREATE TRUNCATE FILE /tmp/test_random.h5");
    HDFql::execute("USE FILE /tmp/test_random.h5");

    HDFql::execute("CREATE CHUNKED DATASET data/vals AS SMALLINT(0 TO UNLIMITED)");

    std::stringstream ss;
    std::random_device rd;
    std::mt19937 eng(rd());
    std::uniform_int_distribution<> dist_vals(0, 500);
    std::uniform_int_distribution<> dist_len(300, 1000);

    for(int i=0; i<500; i++)
    {
        const int num_values = dist_len(eng);
        std::vector<uint16_t> vals;
        for(int j=0; j<num_values; j++)
        {
            const int value = dist_vals(eng);
            vals.push_back(value);
        }

        ss << "ALTER DIMENSION data/vals TO +" << vals.size();
        HDFql::execute(ss.str().c_str()); ss.str("");

        ss << "INSERT INTO data/vals(-" << vals.size() << ":1:1:" << vals.size() 
            << ") VALUES FROM MEMORY " 
            << HDFql::variableTransientRegister(vals.data());
        HDFql::execute(ss.str().c_str()); ss.str("");

    }

    HDFql::execute("CLOSE FILE");

}

答案 1 :(得分:1)

要回复您的上述修改,在将num_values设置为1025的情况下扩展数据集的维度没有问题。

这是我用来测试此代码的代码段:

#include <iostream>
#include "HDFql.hpp"

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

    char script[1024];
    int total_added = 0;
    int num_values = 1025;

    HDFql::execute("CREATE TRUNCATE FILE /tmp/test_random.h5");
    HDFql::execute("USE FILE /tmp/test_random.h5");
    HDFql::execute("CREATE CHUNKED DATASET data/vals AS SMALLINT(0 TO UNLIMITED)");

    for(int i = 0; i < 5000; i++)
    {
        long long dim = 0;
        sprintf(script, "SHOW DIMENSION data/vals INTO MEMORY %d", HDFql::variableTransientRegister(&dim));
        HDFql::execute(script);

        sprintf(script, "ALTER DIMENSION data/vals TO +%d", num_values);
        HDFql::execute(script);

        total_added += num_values;
        std::cout << i << ": " << ":  dim = " << dim << " : added = " << num_values << " (total=" << total_added << ")" << std::endl;
    }

    HDFql::execute("CLOSE FILE");

}

答案 2 :(得分:0)

所以我找出了问题所在-在下面,第一个示例有效,而第二个示例无效:

作品

#include <stdio.h>
#include <random>
#include <HDFql.hpp>

int main (int argc, const char * argv[]) {
    int total_added = 0;
    std::random_device rd;
    std::mt19937 eng(rd());
    std::uniform_int_distribution<> dist_vals(0, 450);
    std::uniform_int_distribution<> dist_len(100, 300);
    const int fixed_buffer_size = 10000;

    HDFql::execute("CREATE TRUNCATE FILE /tmp/test_random.h5");
    HDFql::execute("USE FILE /tmp/test_random.h5");
    HDFql::execute("CREATE CHUNKED DATASET data/vals AS INT(0 TO UNLIMITED)");

    for(int i = 0; i < 5000; i++)
    {
        const int num_values = dist_len(eng);
        std::vector<int> vals(fixed_buffer_size);
        long long dim = 0;
        sprintf(script, "SHOW DIMENSION data/vals INTO MEMORY %d", HDFql::variableTransientRegister(&dim));
        HDFql::execute(script);

        sprintf(script, "ALTER DIMENSION data/vals TO +%d", num_values);
        HDFql::execute(script);

        for(int j=0; j<num_values; j++)
        {
            const int value = dist_vals(eng);
            vals.at(j) = value;
        }
        sprintf(script, "INSERT INTO data/vals(-%d:1:1:%d) VALUES FROM MEMORY %d", num_values, num_values, HDFql::variableTransientRegister(vals.data()));
        HDFql::execute(script);
        HDFql::execute("FLUSH");

        total_added += num_values;
        std::cout << i << ": " << ":  dim = " << dim << " : added = " << num_values << " (total=" << total_added << ")" << std::endl;
    }

    HDFql::execute("CLOSE FILE");
}

失败

#include <stdio.h>
#include <random>
#include <HDFql.hpp>

int main (int argc, const char * argv[]) {
    int total_added = 0;
    std::random_device rd;
    std::mt19937 eng(rd());
    std::uniform_int_distribution<> dist_vals(0, 450);
    std::uniform_int_distribution<> dist_len(100, 300);

    HDFql::execute("CREATE TRUNCATE FILE /tmp/test_random.h5");
    HDFql::execute("USE FILE /tmp/test_random.h5");
    HDFql::execute("CREATE CHUNKED DATASET data/vals AS INT(0 TO UNLIMITED)");

    for(int i = 0; i < 5000; i++)
    {
        const int num_values = dist_len(eng);
        std::vector<int> vals(num_values);
        long long dim = 0;
        sprintf(script, "SHOW DIMENSION data/vals INTO MEMORY %d", HDFql::variableTransientRegister(&dim));
        HDFql::execute(script);

        sprintf(script, "ALTER DIMENSION data/vals TO +%d", num_values);
        HDFql::execute(script);

        for(int j=0; j<num_values; j++)
        {
            const int value = dist_vals(eng);
            vals.at(j) = value;
        }
        sprintf(script, "INSERT INTO data/vals(-%d:1:1:%d) VALUES FROM MEMORY %d", num_values, num_values, HDFql::variableTransientRegister(vals.data()));
        HDFql::execute(script);
        HDFql::execute("FLUSH");

        total_added += num_values;
        std::cout << i << ": " << ":  dim = " << dim << " : added = " << num_values << " (total=" << total_added << ")" << std::endl;
    }

    HDFql::execute("CLOSE FILE");
}

两者之间的唯一区别是,在第一个中,数据缓冲区vals的大小是固定的,而在第二个中,数据缓冲区的大小是动态且随机创建的。

我不明白为什么会发生此错误,因为在c ++中,std::vectorsupposed,使基础数据位于内存中并与C数组和指针魔术完全兼容。但是很明显,编译器在每个示例中都做不同的事情。无论如何,我希望这对其他人有帮助-解决方案是使用固定大小的数据缓冲区。