是否可以通过在matlab中调用c / c ++代码来加速matlab绘图? [英] is it possible to speed-up matlab plotting by calling c / c++ code in matlab?

查看:160
本文介绍了是否可以通过在matlab中调用c / c ++代码来加速matlab绘图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常很容易在Matlab中调用 mex 文件(用c / c ++编写)来加速某些计算。然而,在我的经验中,Matlab的真正瓶颈是数据绘图。创建句柄非常昂贵,即使你只更新句柄数据(例如XData,YData,ZData),这可能需要时间。更糟糕的是,由于Matlab是一个单线程程序,不可能同时更新多个图。

It is generally very easy to call mex files (written in c/c++) in Matlab to speed up certain calculations. In my experience however, the true bottleneck in Matlab is data plotting. Creating handles is extremely expensive and even if you only update handle data (e.g., XData, YData, ZData), this might take ages. Even worse, since Matlab is a single threaded program, it is impossible to update multiple plots at the same time.

因此我的问题是否可以编写一个Matlab GUI并调用C ++(或其他可并行化代码)来处理绘图/可视化?我正在寻找一个跨平台解决方案,将在Windows上工作, Mac和Linux,但任何解决方案,让我开始在任一操作系统是非常感谢!

Therefore my question: Is it possible to write a Matlab GUI and call C++ (or some other parallelizable code) which would take care of the plotting / visualization? I'm looking for a cross-platform solution that will work on Windows, Mac and Linux, but any solution that get's me started on either OS is greatly appreciated!

我发现了一个 C ++库,似乎使用Matlab的 plot()语法,但我不知道这是否会加速,我害怕如果我绘制Matlab的 figure()窗口,事情可能会再次减慢。

I found a C++ library that seems to use Matlab's plot() syntax but I'm not sure whether this would speed things up, since I'm afraid that if I plot into Matlab's figure() window, things might get slowed down again.

将欣赏任何意见和反馈从处理这种情况之前的人的反馈!

I would appreciate any comments and feedback from people who have dealt with this kind of situation before!

编辑:显然,我已经剖析了我的代码,瓶颈是绘图(十几个面板有大量的数据)。

obviously, I've already profiled my code and the bottleneck is the plotting (dozen of panels with lots of data).

EDIT2:为了获得赏金,我需要一个真实的生活,最小的工作示例,如何做到这一点 - 建议的答案不会帮助我。

for you to get the bounty, I need a real life, minimal working example on how to do this - suggestive answers won't help me.

EDIT3:关于要绘制的数据:在一个最简单的情况下,考虑需要更新的20个线图每秒钟都有1000000个数据点。

regarding the data to plot: in a most simplistic case, think about 20 line plots, that need to be updated each second with something like 1000000 data points.

EDIT4:我知道这是一个巨大的积分点,但我从来没有说过问题很容易。我不能只是忽略某些数据点,因为在实际绘制它们之前,没有办法评估哪些点是重要的(数据以亚秒的时间分辨率采样)。事实上,我的数据是使用带有数据查看器(用c ++编写的)的商业数据采集系统采集的。这个程序没有问题可视化多达60个线图,甚至超过1000000个数据点。

I know that this is a huge amount of points to plot but I never said that the problem was easy. I can not just leave out certain data points, because there's no way of assessing what points are important, before actually plotting them (data is sampled a sub-ms time resolution). As a matter of fact, my data is acquired using a commercial data acquisition system which comes with a data viewer (written in c++). This program has no problem visualizing up to 60 line plots with even more than 1000000 data points.

EDIT5:我不喜欢当前讨论的地方。我知道,子采样我的数据可能会加快事情 - 但是,这不是问题。这里的问题是如何获得ac / c ++ / python / java接口使用matlab,希望通过直接谈话硬件(或使用任何其他技巧/方式)加快绘图

I don't like where the current discussion is going. I'm aware that sub-sampling my data might speeds up things - however, this is not the question. The question here is how to get a c / c++ / python / java interface to work with matlab in order hopefully speed up plotting by talking directly to the hardware (or using any other trick / way)

推荐答案

由于你想要最大的性能,你应该考虑写一个最小的OpenGL查看器。将所有点转储到一个文件,并使用MATLAB中的系统命令启动查看器。观众可以很简单。这里是使用GLUT实现的,为Mac OS X编译。代码是跨平台的,所以你应该能够为你提到的所有平台编译它。

Since you want maximum performance you should consider writing a minimal OpenGL viewer. Dump all the points to a file and launch the viewer using the "system"-command in MATLAB. The viewer can be really simple. Here is one implemented using GLUT, compiled for Mac OS X. The code is cross platform so you should be able to compile it for all the platforms you mention. It should be easy to tweak this viewer for your needs.

如果您能够更贴近地将这个查看器集成到MATLAB中,您可以不必使用这个查看器写入和读取文件(=更快的更新)。但是,我没有经验的事情。也许你可以把这个代码放在一个mex文件中?

If you are able to integrate this viewer more closely with MATLAB you might be able to get away with not having to write to and read from a file (= much faster updates). However, I'm not experienced in the matter. Perhaps you can put this code in a mex-file?

编辑:我更新了代码从CPU内存指针绘制一个线条。

I've updated the code to draw a line strip from a CPU memory pointer.

// On Mac OS X, compile using: g++ -O3 -framework GLUT -framework OpenGL glview.cpp
// The file "input" is assumed to contain a line for each point:
// 0.1 1.0
// 5.2 3.0
#include <vector>
#include <sstream>
#include <fstream>
#include <iostream>
#include <GLUT/glut.h>
using namespace std;
struct float2 { float2() {} float2(float x, float y) : x(x), y(y) {} float x, y; };
static vector<float2> points;
static float2 minPoint, maxPoint;
typedef vector<float2>::iterator point_iter;
static void render() {
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(minPoint.x, maxPoint.x, minPoint.y, maxPoint.y, -1.0f, 1.0f);
    glColor3f(0.0f, 0.0f, 0.0f);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, sizeof(points[0]), &points[0].x);
    glDrawArrays(GL_LINE_STRIP, 0, points.size());
    glDisableClientState(GL_VERTEX_ARRAY);
    glutSwapBuffers();
}
int main(int argc, char* argv[]) {
    ifstream file("input");
    string line;
    while (getline(file, line)) {
        istringstream ss(line);
        float2 p;
        ss >> p.x;
        ss >> p.y;
        if (ss)
            points.push_back(p);
    }
    if (!points.size())
        return 1;
    minPoint = maxPoint = points[0];
    for (point_iter i = points.begin(); i != points.end(); ++i) {
        float2 p = *i;
        minPoint = float2(minPoint.x < p.x ? minPoint.x : p.x, minPoint.y < p.y ? minPoint.y : p.y);
        maxPoint = float2(maxPoint.x > p.x ? maxPoint.x : p.x, maxPoint.y > p.y ? maxPoint.y : p.y);
    }
    float dx = maxPoint.x - minPoint.x;
    float dy = maxPoint.y - minPoint.y;
    maxPoint.x += dx*0.1f; minPoint.x -= dx*0.1f;
    maxPoint.y += dy*0.1f; minPoint.y -= dy*0.1f;
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(512, 512);
    glutCreateWindow("glview");
    glutDisplayFunc(render);
    glutMainLoop();
    return 0;
}

编辑:这里是基于下面讨论的新代码。它呈现一个由20个vbos组成的sin函数,每个包含100k点。每个渲染帧添加10k个新点。这使得总共2M点。

Here is new code based on the discussion below. It renders a sin function consisting of 20 vbos, each containing 100k points. 10k new points are added each rendered frame. This makes a total of 2M points. The performance is real-time on my laptop.

// On Mac OS X, compile using: g++ -O3 -framework GLUT -framework OpenGL glview.cpp
#include <vector>
#include <sstream>
#include <fstream>
#include <iostream>
#include <cmath>
#include <iostream>
#include <GLUT/glut.h>
using namespace std;
struct float2 { float2() {} float2(float x, float y) : x(x), y(y) {} float x, y; };
struct Vbo {
    GLuint i;
    Vbo(int size) { glGenBuffersARB(1, &i); glBindBufferARB(GL_ARRAY_BUFFER, i); glBufferDataARB(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW); } // could try GL_STATIC_DRAW
    void set(const void* data, size_t size, size_t offset) { glBindBufferARB(GL_ARRAY_BUFFER, i); glBufferSubData(GL_ARRAY_BUFFER, offset, size, data); }
    ~Vbo() { glDeleteBuffers(1, &i); }
};
static const int vboCount = 20;
static const int vboSize = 100000;
static const int pointCount = vboCount*vboSize;
static float endTime = 0.0f;
static const float deltaTime = 1e-3f;
static std::vector<Vbo*> vbos;
static int vboStart = 0;
static void addPoints(float2* points, int pointCount) {
    while (pointCount) {
        if (vboStart == vboSize || vbos.empty()) {
            if (vbos.size() >= vboCount+2) { // remove and reuse vbo
                Vbo* first = *vbos.begin();
                vbos.erase(vbos.begin());
                vbos.push_back(first);
            }
            else { // create new vbo
                vbos.push_back(new Vbo(sizeof(float2)*vboSize));
            }
            vboStart = 0;
        }

        int pointsAdded = pointCount;

        if (pointsAdded + vboStart > vboSize)
            pointsAdded = vboSize - vboStart;

        Vbo* vbo = *vbos.rbegin();
        vbo->set(points, pointsAdded*sizeof(float2), vboStart*sizeof(float2));

        pointCount -= pointsAdded;
        points += pointsAdded;
        vboStart += pointsAdded;
    }
}
static void render() {
    // generate and add 10000 points
    const int count = 10000;
    float2 points[count];
    for (int i = 0; i < count; ++i) {
        float2 p(endTime, std::sin(endTime*1e-2f));
        endTime += deltaTime;
        points[i] = p;
    }
    addPoints(points, count);
    // render
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(endTime-deltaTime*pointCount, endTime, -1.0f, 1.0f, -1.0f, 1.0f);
    glColor3f(0.0f, 0.0f, 0.0f);
    glEnableClientState(GL_VERTEX_ARRAY);
    for (size_t i = 0; i < vbos.size(); ++i) {
        glBindBufferARB(GL_ARRAY_BUFFER, vbos[i]->i);
        glVertexPointer(2, GL_FLOAT, sizeof(float2), 0);

        if (i == vbos.size()-1)
            glDrawArrays(GL_LINE_STRIP, 0, vboStart);
        else
            glDrawArrays(GL_LINE_STRIP, 0, vboSize);
    }
    glDisableClientState(GL_VERTEX_ARRAY);
    glutSwapBuffers();
    glutPostRedisplay();
}
int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(512, 512);
    glutCreateWindow("glview");
    glutDisplayFunc(render);
    glutMainLoop();
    return 0;
}

这篇关于是否可以通过在matlab中调用c / c ++代码来加速matlab绘图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆