2D histogram problem

So I am running this message pipe to a ROOT thread, but at some point, the graph loop does something and the this thread starts enqueing messages. I remember there is no OpenGl support for 2D hists, but I wonder if there is something else to account for in this situation ? I am receiving a message each 100ms and making a buffer of about 500 samples, which is not much. The pipe flows correctly until I reach the ROOT thread, so maybe there is some tip on how to get this to flow better ? Thanks!

Can you provide a small example reproducing your problem?

thanks, so basically, this is it :

    TApplication RootMarketApp("App", 0, 0);


    auto json = std::make_unique<jsontools::CommonTools>();

    gStyle->SetCanvasPreferGL(kTRUE);


    auto canvas = std::make_unique<TCanvas>("canvas", "CWT", 200, 10, 2048, 1080);

    canvas->Divide(1, 2);

    std::vector<std::vector<float>> signalVector;

    int messageCounter = 0;

    bool initialized = false;

    while (true)
    {

        signalsock->dualsockB->recv(&signalsock->message);

        std::string signalString = signalsock->message.to_string();


        if (initialized == true)
        {
        }
        else
        {
            if (!signalString.empty())
            {
                messageCounter += 1;
            }
        }

        if (messageCounter > 100)
        {
            initialized = true;

            std::vector<float> serializedSignal = json->stringToVecProc(messageStringBuys);
            signalVector.push_back(serializedSignal);

            auto hist2sig = std::make_unique<TH2D>("hist2sig", "CWTHist2dsig", signalVector.size(), 0, signalVector.size(), signalVector.at(0).size(), 0, signalVector.at(0).size());
            hist2droc->SetFillColor(55);
            hist2droc->SetStats(0);
            hist2droc->SetTitle("2D ROC");
            canvas->cd(1);
            hist2droc->Draw("COL");


            for (int steps = 0; steps < signalVector.size(); ++steps)

            {
                for (int scales = 0; scales < signalVector.at(0).size(); ++scales)

                {
                    hist2sig->Fill(steps, scales, signalVector[steps][scales]);
                }
            }

            canvas->cd(1);
            canvas->Update();
            canvas->Pad()->Draw();

            canvas->Modified();
            gSystem->ProcessEvents();

        }

        if (signalVector.size() > 500)
        {
            signalVector.erase(signalVector.begin());
        }
    }

It’s a while loop that receives a message at 10Hz rate after a warm-up period, the Hist starts being filled … and everything goes well until it starts getting bogged down until it makes the pipe stop, seemingly waiting for the graph to process data and consume the remaining messages in the buffer. The pipe resumes a while after, and it’s a cycle from there. I just re-installed my NVIDIA drivers and gStyle->SetCanvasPreferGL(kTRUE); doesn’t error anymore, but I haven’t noticed any improvement on performance. I’m sure I’m doing something wrong but I can’t figure out where this is happening in this thread … thanks.

EDIT: The problem gets aggravated when I have two hists ( canvas divided by 2 ) updating at the same time, from the same source ( the same message )

EDIT: It seems to be the size of the buffer has a lot to do with it. If I reduce the size to half of it ( 250 on this case ) it seems to work much better and the timestamps are synced. But I thought 500 was already a low quantity … is there any way to get around this ?

  canvas->Pad()->Draw();

?

Why are you doing this?

I was using older code I had where I did the same, I believe I asked and somebody told me to use it. I might have mixed it somehow. I have removed it and it improves a little, but still what seems to be decissive is the size of the buffer. At 250 size it seems mostly in sync, but if I go higher than that, the mentioned effect occurs

signalVector.size() = 250 ? This value is the number of bons for the 2D histogram you are creating by the line:

 auto hist2sig = std::make_unique<TH2D>("hist2sig", "CWTHist2dsig", signalVector.size(), 0, signalVector.size(), signalVector.at(0).size(), 0, signalVector.at(0).size());

In your case, this is the number of bins along the X and Y axis. TH2D are memory resident objects. It means that each time you create such a histogram you need a memory space equal to 250x250xsize_of_double . Do you have enough memory for that ?

at 250 it works well tho, and yes I do have enough memory … it’s starting at around 500 size that it gets clogged, but memory usage is only a little more, so it doesn’t look like a RAM problem. I still have half my RAM available when running it

Are you sure it is hist2droc->Draw("COL"); which creates the problem? what about if you do not draw? do you still see a slow down when you increase the size?

Ok so I have tested without the iteration / hist fill part, I have removed only this block :

            for (int steps = 0; steps < signalVector.size(); ++steps)

            {
                for (int scales = 0; scales < signalVector.at(0).size(); ++scales)

                {
                    hist2sig->Fill(steps, scales, signalVector[steps][scales]);
                }
            }

And it works fine, perfect sync ( I am printing the timestamps on the canvas ) I wonder if I’m doing something wrong here ? thanks !

And you kept the drawing?
So it seems the time is spent on filling. The loops by themselves might take time.
Not sure how “big” they are…

yes, of the whole code block I have posted at the start of the thread, I only remove the iterations / fill and then if works fine. Do you think threading the loops / filling is possible or that it can improve the performance ? Thanks !

I am not sure, but instead of the two loops, you might use FillN ?

do I still have to loop ? or it’s just somehow mapped ?

I am trying hist2d->FillN(100,signalVector,signalVector.data()); but I get incorrect argument match

I can’t find any tutorial that uses the method … thanks

FillN fills from an array. It should avoid the loop.
see:
https://root.cern/doc/master/unuranDemo_8C.html
@moneta might help.

Hi,
Since you have a TH2 histogram , it seems you are using a
[TH2::FillN] (ROOT: TH2 Class Reference),
which will require two double * pointer’s for the x and y coordinates and optionally a pointer for the weight.
From the code it seems to be you are looping trough the bins and set the values.
If you have the bin numbers, better to loop through them and use TH2::SetBinContent,
if instead you have arrays of x and y values, you should use FillN as

std::vector<double> x = ..... // array of x values 
std::vector<double> y = ... // array of y values  (same size as x)
std::vector<double> w = .... // array of weights  (same size as x)
hist2d->FillN(x.size(),x.data(), y.data(), w.data());

and if you don’t have weights (all weights are 1) just pass a nullptr instead of w.

Lorenzo

thanks !

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.