Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added multi-threaded scan matching using OpenMP #14

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

eybee
Copy link

@eybee eybee commented Nov 8, 2016

I profiled the gmapping process and found that the scan matching particle filter is very time consuming.
It easily forces even more modern CPU cores to 100% load on larger particle numbers utilizing only one core.
With the few changes I made, the scan matching process is now multi-threaded using the OpenMP library.
This results in a much better performance of gmapping in total.
I tested the package on three different platforms;

Cartograhger Turtlebot testbag laser scan:  
80 particles:

Ubuntu VM Laptop Intel i5:
single-threaded: Scan matching took: 1.59643
multi-threaded:  Scan matching took: 0.721148

Speedup = 2.21


Intel NUC Turtlebot:
single-threaded: Scan matching took: 4.32706
multi-threaded:  Scan matching took: 2.3869

Speedup = 1.81


20 particles:

PicoZed ARM v7:
single-threaded: Scan matching took: 5.19983
multi-threaded:  Scan matching took: 3.09518

Speedup = 1.68

@@ -1,6 +1,6 @@
<package>
<name>openslam_gmapping</name>
<version>0.1.2</version>
<version>0.1.3</version>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't change that file please

@@ -6,6 +6,7 @@ find_package(catkin)
catkin_package(
INCLUDE_DIRS include
LIBRARIES gridfastslam scanmatcher sensor_base sensor_range sensor_odometry utils
DEPENDS OpenMP
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not necessary

if(OPENMP_FOUND)
message(STATUS "OPENMP FOUND")
set(OpenMP_FLAGS ${OpenMP_CXX_FLAGS}) # or if you use C: ${OpenMP_C_FLAGS}
set(OpenMP_LIBS gomp)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add_library(gridfastslam
gfsreader.cpp
gridslamprocessor.cpp
gridslamprocessor_tree.cpp
motionmodel.cpp
)
target_link_libraries(gridfastslam scanmatcher sensor_range)

target_link_libraries(gridfastslam scanmatcher sensor_range ${OpenMP_LIBS})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should not be changed I believe.

@@ -243,6 +245,7 @@ namespace GMapping {
/**minimum score for considering the outcome of the scanmatching good*/
PARAM_SET_GET(double, minimumScore, protected, public, public);


Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessary blank line

@@ -15,6 +15,8 @@
#include <gmapping/scanmatcher/scanmatcher.h>
#include "motionmodel.h"

#include <omp.h>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't be necessary.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's necessary because I'm calling theomp_get_wtime() function to measure execution time.

// the functions below performs side effect on the internal structure,
//should be called only inside the processScan method
private:

std::vector<double> durations;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is that a member and not created before the for loop in the scanMatch function ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because I want to store the execution time of each function call. so it has to be valid outside the function's scope as well.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use two members such as sumscore and update_count to compute the average execution time, since the execution time of each function call is of little use?

@eybee
Copy link
Author

eybee commented Nov 20, 2016

Changed the things you mentioned.

@eybee
Copy link
Author

eybee commented Nov 22, 2016

If I use an openmp function, I do have to link against it of course.

@eybee
Copy link
Author

eybee commented Nov 23, 2016

I realized that I also need to keep the set(CXX_FLAGS) because no optimization is done otherwise.

@alittleharry
Copy link

alittleharry commented Dec 5, 2016

hi, i found using openmp would result in core dump such as "corrupted double-linked list" more often, did you ever met that?

@eybee
Copy link
Author

eybee commented Dec 5, 2016

No, I never had that issue. Could you run valgrind on it and post the result?

@alittleharry
Copy link

RESAMPLE**
Deleting Nodes: 7 11 18 26 29 Done
Deleting old particles...Done
Copying Particles and Registering scans... Done
update frame 1808
update ld=1.04128 ad=0.0346855
Laser Pose= 121.1 37.684 -2.40904
m_count 185
Average Scan Matching Score=333.415
Average Scan Matching Time=0.143367s
neff= 28.2199
Registering Scans:[slam_gmapping-1] process has died [pid 8614, exit code -9, cmd /mnt/hgfs/catkin_tool/devel/lib/gmapping/slam_gmapping scan:=velodyne_2d_laserscan __name:=slam_gmapping __log:=/home/alittleharry/.ros/log/0817e1f4-bae4-11e6-8ead-000c297eec31/slam_gmapping-1.log].
log file: /home/harry/.ros/log/0817e1f4-bae4-11e6-8ead-000c297eec31/slam_gmapping-1*.log==8595== Thread 2:
==8595== Invalid read of size 4
==8595== at 0x5506BE: PyObject_Free (in /usr/bin/python2.7)
==8595== by 0x4F57A3: PyFile_WriteObject (in /usr/bin/python2.7)
==8595== by 0x436A3D: ??? (in /usr/bin/python2.7)
==8595== by 0x49EC75: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x49AB44: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x49AB44: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x49AB44: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x499EF1: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A1C99: ??? (in /usr/bin/python2.7)
==8595== Address 0x95ba020 is 528 bytes inside a block of size 1,449 free'd
==8595== at 0x4C2CB8A: realloc (vg_replace_malloc.c:785)
==8595== by 0x52D088: _PyString_Resize (in /usr/bin/python2.7)
==8595== by 0x510770: PyUnicodeUCS4_EncodeUTF8 (in /usr/bin/python2.7)
==8595== by 0x4BD3FE: ??? (in /usr/bin/python2.7)
==8595== by 0x4E2CD1: PyCodec_Encode (in /usr/bin/python2.7)
==8595== by 0x5B6BB0: PyUnicodeUCS4_AsEncodedString (in /usr/bin/python2.7)
==8595== by 0x4F5839: PyFile_WriteObject (in /usr/bin/python2.7)
==8595== by 0x436A3D: ??? (in /usr/bin/python2.7)
==8595== by 0x49EC75: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x49AB44: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== Block was alloc'd at
==8595== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==8595== by 0x52A287: PyString_FromStringAndSize (in /usr/bin/python2.7)
==8595== by 0x5107A2: PyUnicodeUCS4_EncodeUTF8 (in /usr/bin/python2.7)
==8595== by 0x4BD3FE: ??? (in /usr/bin/python2.7)
==8595== by 0x4E2CD1: PyCodec_Encode (in /usr/bin/python2.7)
==8595== by 0x5B6BB0: PyUnicodeUCS4_AsEncodedString (in /usr/bin/python2.7)
==8595== by 0x4F5839: PyFile_WriteObject (in /usr/bin/python2.7)
==8595== by 0x436A3D: ??? (in /usr/bin/python2.7)
==8595== by 0x49EC75: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x49AB44: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595==

all processes on machine have died, roslaunch will exit
shutting down processing monitor...
... shutting down processing monitor complete
done
==8595== Thread 1:
==8595== Invalid read of size 4
==8595== at 0x5506BE: PyObject_Free (in /usr/bin/python2.7)
==8595== by 0x507EAF: PyDict_SetItem (in /usr/bin/python2.7)
==8595== by 0x4F7F70: _PyModule_Clear (in /usr/bin/python2.7)
==8595== by 0x4C7CAD: PyImport_Cleanup (in /usr/bin/python2.7)
==8595== by 0x437D4B: Py_Finalize (in /usr/bin/python2.7)
==8595== by 0x44F992: Py_Main (in /usr/bin/python2.7)
==8595== by 0x5076F44: (below main) (libc-start.c:287)
==8595== Address 0x682f020 is 30,592 bytes inside a block of size 32,816 free'd
==8595== at 0x4C2BD57: free (vg_replace_malloc.c:530)
==8595== by 0x5111F2C: closedir (closedir.c:50)
==8595== by 0x4CDAE1: ??? (in /usr/bin/python2.7)
==8595== by 0x49968C: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A2D2D: ??? (in /usr/bin/python2.7)
==8595== by 0x49990E: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A2CA3: ??? (in /usr/bin/python2.7)
==8595== by 0x49990E: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A2CA3: ??? (in /usr/bin/python2.7)
==8595== by 0x49990E: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x499EF1: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x499EF1: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== Block was alloc'd at
==8595== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==8595== by 0x5111DF0: __alloc_dir (opendir.c:207)
==8595== by 0x4CD915: ??? (in /usr/bin/python2.7)
==8595== by 0x49968C: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A2D2D: ??? (in /usr/bin/python2.7)
==8595== by 0x49990E: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A2CA3: ??? (in /usr/bin/python2.7)
==8595== by 0x49990E: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A2CA3: ??? (in /usr/bin/python2.7)
==8595== by 0x49990E: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x499EF1: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x499EF1: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595==
==8595== Invalid read of size 4
==8595== at 0x5506BE: PyObject_Free (in /usr/bin/python2.7)
==8595== by 0x4F792B: ??? (in /usr/bin/python2.7)
==8595== by 0x507EAF: PyDict_SetItem (in /usr/bin/python2.7)
==8595== by 0x4F7F70: _PyModule_Clear (in /usr/bin/python2.7)
==8595== by 0x4C7CAD: PyImport_Cleanup (in /usr/bin/python2.7)
==8595== by 0x437D4B: Py_Finalize (in /usr/bin/python2.7)
==8595== by 0x44F992: Py_Main (in /usr/bin/python2.7)
==8595== by 0x5076F44: (below main) (libc-start.c:287)
==8595== Address 0x5eec020 is 0 bytes inside a block of size 722 free'd
==8595== at 0x4C2BD57: free (vg_replace_malloc.c:530)
==8595== by 0x4F7B5E: ??? (in /usr/bin/python2.7)
==8595== by 0x4F78C3: ??? (in /usr/bin/python2.7)
==8595== by 0x507EAF: PyDict_SetItem (in /usr/bin/python2.7)
==8595== by 0x4F7F70: _PyModule_Clear (in /usr/bin/python2.7)
==8595== by 0x4C7CAD: PyImport_Cleanup (in /usr/bin/python2.7)
==8595== by 0x437D4B: Py_Finalize (in /usr/bin/python2.7)
==8595== by 0x44F992: Py_Main (in /usr/bin/python2.7)
==8595== by 0x5076F44: (below main) (libc-start.c:287)
==8595== Block was alloc'd at
==8595== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==8595== by 0x52A287: PyString_FromStringAndSize (in /usr/bin/python2.7)
==8595== by 0x523BB8: ??? (in /usr/bin/python2.7)
==8595== by 0x523EBF: ??? (in /usr/bin/python2.7)
==8595== by 0x523DF7: ??? (in /usr/bin/python2.7)
==8595== by 0x523ED5: ??? (in /usr/bin/python2.7)
==8595== by 0x5AAD55: PyMarshal_ReadObjectFromString (in /usr/bin/python2.7)
==8595== by 0x5AADFF: PyMarshal_ReadLastObjectFromFile (in /usr/bin/python2.7)
==8595== by 0x5AAE3D: ??? (in /usr/bin/python2.7)
==8595== by 0x5B1EC4: ??? (in /usr/bin/python2.7)
==8595== by 0x540947: ??? (in /usr/bin/python2.7)
==8595== by 0x540D07: ??? (in /usr/bin/python2.7)
==8595==
==8595== Invalid read of size 4
==8595== at 0x57398A: PyObject_GC_Del (in /usr/bin/python2.7)
==8595== by 0x4F6DB6: ??? (in /usr/bin/python2.7)
==8595== by 0x4B8C97: ??? (in /usr/bin/python2.7)
==8595== by 0x507EAF: PyDict_SetItem (in /usr/bin/python2.7)
==8595== by 0x4F7F70: _PyModule_Clear (in /usr/bin/python2.7)
==8595== by 0x4C7D60: PyImport_Cleanup (in /usr/bin/python2.7)
==8595== by 0x437D4B: Py_Finalize (in /usr/bin/python2.7)
==8595== by 0x44F992: Py_Main (in /usr/bin/python2.7)
==8595== by 0x5076F44: (below main) (libc-start.c:287)
==8595== Address 0x6c11020 is 16 bytes after a block of size 16 free'd
==8595== at 0x4C2BD57: free (vg_replace_malloc.c:530)
==8595== by 0x55AD14: ??? (in /usr/bin/python2.7)
==8595== by 0x6C6B0AA: ??? (in /usr/lib/python2.7/lib-dynload/_elementtree.x86_64-linux-gnu.so)
==8595== by 0x6C6AEE8: ??? (in /usr/lib/python2.7/lib-dynload/_elementtree.x86_64-linux-gnu.so)
==8595== by 0x6C6B063: ??? (in /usr/lib/python2.7/lib-dynload/_elementtree.x86_64-linux-gnu.so)
==8595== by 0x55A656: ??? (in /usr/bin/python2.7)
==8595== by 0x4F6D86: ??? (in /usr/bin/python2.7)
==8595== by 0x49975A: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x499EF1: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x499EF1: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x499EF1: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== Block was alloc'd at
==8595== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==8595== by 0x52FCD6: PyList_New (in /usr/bin/python2.7)
==8595== by 0x6C67F86: ??? (in /usr/lib/python2.7/lib-dynload/_elementtree.x86_64-linux-gnu.so)
==8595== by 0x6C65E57: ??? (in /usr/lib/python2.7/lib-dynload/_elementtree.x86_64-linux-gnu.so)
==8595== by 0x70CBF69: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.6.0)
==8595== by 0x70CC64D: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.6.0)
==8595== by 0x70CA9E0: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.6.0)
==8595== by 0x70CB16C: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.6.0)
==8595== by 0x70CE5DE: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.6.0)
==8595== by 0x6C6461C: ??? (in /usr/lib/python2.7/lib-dynload/_elementtree.x86_64-linux-gnu.so)
==8595== by 0x49968C: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595==
==8595== Invalid read of size 4
==8595== at 0x55EAA2: PyGrammar_RemoveAccelerators (in /usr/bin/python2.7)
==8595== by 0x437DB6: Py_Finalize (in /usr/bin/python2.7)
==8595== by 0x44F992: Py_Main (in /usr/bin/python2.7)
==8595== by 0x5076F44: (below main) (libc-start.c:287)
==8595== Address 0x5fd5020 is 32 bytes inside a block of size 112 free'd
==8595== at 0x4C2BD57: free (vg_replace_malloc.c:530)
==8595== by 0x55AD14: ??? (in /usr/bin/python2.7)
==8595== by 0x49AA0E: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x499A51: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x499A51: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x499A51: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x499A51: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== Block was alloc'd at
==8595== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==8595== by 0x52FCD6: PyList_New (in /usr/bin/python2.7)
==8595== by 0x530244: ??? (in /usr/bin/python2.7)
==8595== by 0x49A3B4: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x499A51: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x499A51: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x499A51: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595== by 0x4A090B: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==8595== by 0x499A51: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==8595==
==8595==
==8595== HEAP SUMMARY:
==8595== in use at exit: 2,658,373 bytes in 5,034 blocks
==8595== total heap usage: 162,240 allocs, 157,206 frees, 275,080,482 bytes allocated
==8595==
==8595== LEAK SUMMARY:
==8595== definitely lost: 0 bytes in 0 blocks
==8595== indirectly lost: 0 bytes in 0 blocks
==8595== possibly lost: 30,720 bytes in 54 blocks
==8595== still reachable: 2,627,653 bytes in 4,980 blocks
==8595== suppressed: 0 bytes in 0 blocks
==8595== Rerun with --leak-check=full to see details of leaked memory
==8595==
==8595== For counts of detected and suppressed errors, rerun with: -v
==8595== Use --track-origins=yes to see where uninitialised values come from
==8595== ERROR SUMMARY: 9220 errors from 120 contexts (suppressed: 0 from 0)

@KleinYuan
Copy link

Any follow ups?
@vrabaud @alittleharry

@JohannesBetz
Copy link

Hey everyone,
are there any news about the Multi Thread Integration? I am wondering, if the branch from eybee is finished?
I cloned the repo and did some tests, code is working so far but i dont see much improvement.
So what is the status of the Multi Thread Project?

it->weight+=l;
it->weightSum+=l;
m_particles[i].weight+=l;
m_particles[i].weightSum+=l;

//set up the selective copy of the active area
//by detaching the areas that will be updated
m_matcher.invalidateActiveArea();
Copy link

@topin89 topin89 Nov 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with these two lines:

m_matcher.invalidateActiveArea();
m_matcher.computeActiveArea(m_particles[i].map, m_particles[i].pose, plainReading)

They change map and matcher and they are designed to work sequentially. I suppose we should split this loop in two,
something like

//parallel
#pragma omp parallel for reduction(+:sumScore)
  for (int i = 0; i < m_particles.size(); i++){
    OrientedPoint corrected;
    double score, l, s;

    score=m_matcher.optimize(corrected, m_particles[i].map, m_particles[i].pose, plainReading);
    //    it->pose=corrected;
    if (score>m_minimumScore){
      m_particles[i].pose=corrected;
      // m_infoStream << "Pose was corrected!" << std::endl;
    } else {
	if (m_infoStream){
	  m_infoStream << "Scan Matching Failed, using odometry. Likelihood=" << l <<std::endl;
	  m_infoStream << "lp:" << m_lastPartPose.x << " "  << m_lastPartPose.y << " "<< m_lastPartPose.theta <<std::endl;
	  m_infoStream << "op:" << m_odoPose.x << " " << m_odoPose.y << " "<< m_odoPose.theta <<std::endl;
	}
    }

    m_matcher.likelihoodAndScore(s, l, m_particles[i].map, m_particles[i].pose, plainReading);
    sumScore+=score;
    m_particles[i].weight+=l;
    m_particles[i].weightSum+=l;


    m_matcher.invalidateActiveArea();
    m_matcher.computeActiveArea(m_particles[i].map, m_particles[i].pose, plainReading);
  }

//sequential
  for (int i = 0; i < m_particles.size(); i++){
    //set up the selective copy of the active area
    //by detaching the areas that will be updated
    m_matcher.invalidateActiveArea();
    m_matcher.computeActiveArea(m_particles[i].map, m_particles[i].pose, plainReading);
  }

Also, m_infoStream << ... will be garbled if two or more threads don't get enough score. I suggest either omp critical or plain removal of these debug lines.

EDIT:
Alternatively, in scanmatecher.cpp in registerScan you can place real allocation of memory inside a critical section.

#pragma omp critical(alloc_area)
    {
        map.storage().allocActiveArea();
    }

Copy link
Contributor

@k-okada k-okada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eybee could you create new PR against melodic-devel branch? we have switched from master to melodic-branch when we changed licence to BSD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants