hdf5 - HDFql 从 std::vector 迭代地填充数据集
问题描述
我正在尝试使用 HDFql 迭代地将数据集填充到 HDF5 文件中。我迭代的意思是,我的模拟器偶尔会伴随更新,我希望将更多数据(包含在 a 中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。
解决方案
i
您在外部和内部for
循环中都使用变量,这是错误的。此外,作为建议,您发布的代码片段可以使用以下内容进行优化:
data
创建数据集时无需创建组data/vals
,HDFql 创建data
为组(如果不存在)和vals
数据集。无需
/tmp/test_random.h5
在循环内打开和关闭文件(因为这会降低性能);只需在代码开头打开文件并在代码末尾关闭它。
这是更正/重构的代码:
#include <stdio.h>
#include <random>
#include <HDFql.hpp>
int main (int argc, const char * argv[]) {
HDFql::execute("CREATE TRUNCATE AND 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.str("");
ss << "ALTER DIMENSION data/vals TO +" << vals.size();
HDFql::execute(ss);
ss.str("");
ss << "INSERT INTO data/vals(-" << vals.size() << ":1:1:" << vals.size()
<< ") VALUES FROM MEMORY "
<< HDFql::variableTransientRegister(vals);
HDFql::execute(ss);
}
HDFql::execute("CLOSE FILE");
}
推荐阅读
- javascript - 我想调用一个 Action onSubmit redux 表单
- android - 如何在android中获取PNG格式的图像
- elasticsearch - 如何从 Logstash 的文档字段中提取服务名称
- c# - SharePoint 2013:为什么在创建 clientContext 时出现 500 错误?
- linux - iconv 命令不会将纯文本文件的编码更改为另一种编码
- python - 如何使用 python 抓取使用 base 64 图像编码并存储在数据库中
- typescript - typescript 类装饰器:typescript 编译器无法识别抽象方法
- python - 使用 ansible 和 python 在 Oracle 中更改参数
- python - python如何将动态创建类转储到文件
- reactjs - 将标准化数据存储到 Redux