物理模拟数值数据数据库

时间:2016-11-16 16:13:48

标签: mongodb simulation physics database

我从事理论物理工作,并且做了大量的计算机模拟。我的职责的一个重要部分是对结果的分析。我进行模拟并将数值结果存储在一个简单名称的文件中。通常我有很多名称非常相似的数据文件,过了一段时间我不记得文件对应的参数类型。我在想,也许存在一种更好的方法来存储来自模拟的数值结果,例如一些数据库(SQL,MongoDB等),我可以在其中放置一些关于程序参数,名称,日期等的评论 - 一种带有数字数据的库。我只是在一个地方组织得很好。你知道这样的事吗?你如何存储计算机模拟的数值数据?

更多详情

典型程序如下所示。假设我们想模拟三体问题的时间演变。我们有三个不同质量的物体与牛顿力相互作用。我想测试这些物体如何在空间中移动,具体取决于:相对质量值,初始位置 - 6个参数。我为一个参数选择运行模拟并将其保存在文件中:three_body_m1 = 0p1_m2 = 0p3_(其余).dat - 一个文件中总共1 + 3 * 3(3d)列数据的所有双精度。然后我午餐gnuplot,python等,并将它们可视化。原则上,不同模拟的数据之间没有关系,但我可以用它们来制作比较图。

1 个答案:

答案 0 :(得分:1)

在相同的nodejs上下文中,您可以

  • 使用socket.io-stream + fs模块将大xyz数据文件流式传输到服务器,并使用mongodb模块将文件名+参数保存到数据库。(最多1页编码,但更多用于复杂的服务器通话)

  • 如果数据适合ram并且您不必立即保存,则可以使用redis模块轻松地将所有内容发送到服务器缓存(作为键值对,例如data-> xyzData和parameters- > simulationParameters和user-> name_surname)并从中高速读取。如果您需要服务器中的其他进程将数据作为文件,您可以转而使用ramdisk,并将大部分RAM带宽作为文件缓存。(需要更多的ram,但速度很快)

  • mongodb缓慢(即使有优化)用于保存数百万个粒子xyz数据,但这是最简单,最快速的参数保存和共享安装。

使用all可能会更好。

  • 保存:使用socket.io-stream和fs将文件流转换为物理磁盘。将参数发送到mongodb。
  • 正在加载:如果用户已注册,请检查redis,检查数据是否在缓存中,如果是,则获取它,如果不是,则从物理磁盘流传输并同时将其中的一部分保存到redis。
  • 编辑:检查缓存是否存在,如果是,则编辑它。另一个服务器端进程可以从该缓存更新物理磁盘,如果没有则直接更新物理磁盘。

通讯方案可以是:

  • 如果有任何待处理的写入/读取/编辑,数据服务器会与缓存服务器进行对话,从中消耗作业。

  • 计算服务器与缓存服务器的对话,以生成读/写/编辑作业或使用计算作业。

  • 客户端可以与缓存服务器通信以进行只读。

  • 管理员也可以放置自己的数据或制作计算作业或阅读内容。

  • 计算服务器,数据服务器和缓存服务器可以轻松地放在同一台计算机上,也可以移动到其他计算机上,这要归功于nodejs的强大功能和无数模块,如redis,socket.io-stream,fs,ejs,express(例如,客户等

  • 缓存服务器可以将一些数据卸载到另一个缓存服务器并重定向(或者将数据映射到它)

  • 只要RAM保持,缓存服务器就可以同时传送N个数据服务器和M个计算服务器。

你的网络速度慢吗?您只需使用3-5行额外代码(两端)即可使用gzip模块即时压缩数据

你没钱?

  • Nodejs适用于raspberry pi(可能是数据服务器吗?)
  • Nvidia GTX660可以与英特尔galileo(计算服务器?)一起使用nodejs和一些额外的本机模块用于opencl(可能难以实现)(也连接(和供电)gpu和galileo可能并不容易但应该很多比用于fp32数字运算的覆盆子pi板更快
  • 绕过缓存,RAM现在很贵。
 data server cluster
               \
                \
                 \                        client
                  \             client    /
                   \            /        /
                    \          /        /
               mainframe cache and database server ----- compute cluster
                          |                   \
                          |                    \
                    support cache server        admin

将一些文件发送到另一台计算机(或同一台)的一个非常简单的示例:

var pipeline_n = 8;


var fs = require("fs");

// server part accepting files
{
    var io = require('socket.io').listen(80);
    var ss = require('socket.io-stream');
    var path = require('path');
    var ctr = 0;
    var ctr2 = 0;
    io.of('/user').on('connection', function (socket) {

        var z1 = new Date();

        for (var i = 0; i < pipeline_n; i++) {
            ss(socket).on('data'+i.toString(), function (stream, data) {
                var t1 = new Date();
                stream.pipe(fs.createWriteStream("m://bench_server" + ctr + ".txt"));
                ctr++;
                stream.on("finish", function (p) {
                    var len = stream._readableState.pipes.bytesWritten;
                    var t2 = new Date();


                    ctr2++;
                    if (ctr2 == pipeline_n) {
                        var z2 = new Date();
                        console.log(len * pipeline_n);
                        console.log((z2 - z1));
                        console.log("throughput: " + ((len * pipeline_n) / ((z2 - z1)/1000.0))/(1024*1024)+" MB/s");
                    }
                });

            });
        }

    });
}


//client or another server part sending a file
//(you can change it to do parts of same file instead of same file n times),
//just a dummy file sending code to stress other server

for (var i = 0; i < pipeline_n; i++)
{
    var io = require('socket.io-client');
    var ss = require('socket.io-stream');

    var socket = io.connect('http://127.0.0.1/user');
    var stream = ss.createStream();
    var filename = 'm://bench.txt'; // ramdrive or cluster of hdd raid

    ss(socket).emit('data'+i.toString(), stream, { name: filename });
    fs.createReadStream(filename).pipe(stream);

}

这是测试mongodb的插入与批量插入性能(这可能是一种错误的基准测试方法,但很简单,只是取消注释 - 在您想要基准测试的部分)

var mongodb = require('mongodb');
var client = mongodb.MongoClient;
var url = 'mongodb://localhost:2019/evdb2';
client.connect(url, function (err, db) {
    if (err) {
        console.log('fail:', err);
    } else {
        console.log('success:', url);
        var collection = db.collection('tablo');

        var bulk = collection.initializeUnorderedBulkOp();


        db.close();

        //benchmark insert
        //var t = 0;
        //t = new Date();
        //var ctr = 0;
        //for (var i = 0; i < 1024 * 64; i++)
        //{
        //    collection.insert({ x: i + 1, y: i, z: i * 10 }, function (e, r) {
        //        ctr++;
        //        if (ctr == 1024 * 64)
        //        {
        //            var t2 = 0;
        //            db.close();
        //            t2 = new Date();
        //            console.log("insert-64k: " + 1000.0 / ((t2.getTime() - t.getTime()) / (1024 * 64)) + " insert/s");
        //        }
        //    });
        //}


        // benchmark bulk insert
        //var t3 = new Date();
        //for (var i = 0; i < 1024 * 64; i++)
        //{
        //    bulk.insert({ x: i + 1, y: i, z: i * 10 });
        //}
        //bulk.execute();
        //var t4 = new Date();
        //console.log("bulk-insert-64k: " + 1000.0/((t4.getTime() - t3.getTime()) / (1024 * 64)) + " insert/s");
        //           db.close();

    }
});

请务必在此之前设置mongodb和/或redis服务器。还有来自nodejs命令提示符的“npm install module_name”必需模块。