Shared Memory Tests

As part of the effort to optimize LHC physics software applications to run on multi-core cpus, this page shows some test examples that clarifies the usage of shared memory within C++. In order to reproduce the examples it is needed the Boost.Interprocess library version 1.35 and GDB version 6.8.

Download sources from here.

Test 1: Two Programs Accessing the Same Shared Objects (read-only)

Description: Two shared objects are created in the master.cc program using boost.interprocess library. The first object is an instance of a POD class (named PODClass). The second object is an instance of a class with virtual functions ( VirtualClass inherits from ParentClass). The slace.cc program tries to access to the shared objects, however when it tries to read the VirtualClass instance it raises a segmentation fault. The PODClass instance can be accessed without any problems.

Explanation: When the program slave.cc tries to access the virtual method it crashes with a segmentation fault because the virtual table is not stored in the same virtual address for both programs. When the second program tries to resolve the virtual method address using a wrong virtual table address we get the segmentation fault.

Test 2: Two Forked Process Accessing the Same Shared Objects (read-only)

Description: Two shared objects are created before [[http://en.wikipedia.org/wiki/Fork_%28operating_system%29][forking]. The first is a POD object and the second has a virtual const method. Both process are created from a single program using fork(). In that case the PODClass and VirtualClass instances can be accessed without any error. As in the Test 1 we try to call a virtual method from the CHILD process.

Explanation: In that case we do not have a segmentation fault crash while accessing the virtual method of the VirtualClass instance. Why? This happens because the copy-on-write fork implementation assures that the virtual address of the virtual table location remains unchanged. Therefore, the CHILD process can resolves the address of the virtual table because the virtual addresses has not changed. The virtual table never changes at run-time. This implies that it is possible to use virtual methods in forked process if the classes (or libraries) has been loaded before the forking.

Test 3: Two Forked Process Accessing non-shared Objects

Description: Two non-shared objects are created before forking. The first is a POD and the second has a virtual method. After forking the PARENT reads and then modifies the string value inside the objects. However, if the CHILD process isnot able to see the changes.

Explanation: This program does not show a segmentation fault. For read-only access copy-on-write implementation of fork() assures that we share the objects (i.e. it's physical memory) as long as we do not modify them. It is a simple way to share read-only memory.

Test 4: Two Forked Process Accessing the Same Shared Objects (read-write)

Description: The PARENT forked process creates two shared objects. The first is a POD object and the second has a virtual method. Both process are created from a single program using fork(). After creating the process in the PARENT we modify its value. We can not see the modified string value in the CHILD process. However, It does not crash.

Comment: In order to debug this test case it is needed [[][GDB 6.8]]. This version provides the functionality to debug programs with multiple processes.

Explanation: In that case the virtual table is shared among process, therefore as we have seen in Test 2 we can resolve the addresses of the virtual methods. The problem in that case is that we are not using the same physical memory to store the std::string. Why? Because the char* inside the std::string is allocated using the default allocator (heap space) and therefore this memory region is not shared at all. This situation is quite general due to the fact that inside C++ objects it is possible to allocate additional memory using the new operator.

Conclusion

The following conclusions has been derived from the usage of a concrete shared memory library (i.e. Boost Interprocess). However, they are general and applies to all of them.

Using shared memory IT IS POSSIBLE to use classes that contains:

  1. Virtual methods provided that we create the process using fork() and the libraries are loaded before forking.
  2. POD without pointers. If pointers are needed an smart pointer should be used instead.

Using shard memory IT IS NOT POSSIBLE to use classes that contains:

  1. Static members will not be shared. The static members as the virtual table resides in the data segment. This implies that static data members can only be used for read only purposes.
  2. Pointers
  3. Virtual classes in different programs
  4. Virtual classes in shared libraries loaded after the fork

The previous points implies that the usage of shared memory can not be transparent to C++ developers.

References

U. Drepper, What Every Programmer Should Know About Memory, 2007.

GDB Debugger Documentation

Downloads

multhreading20080528.zip: Test sources. Requisites: Boost 1.35, gcc 3.4 and gdb 6.8

Topic attachments
I Attachment History Action Size Date Who Comment
Compressed Zip archivezip multhreading20080528.zip r1 manage 966.1 K 2008-05-29 - 17:38 MarcMagransDeAbril Test sources. Requisites: Boost 1.35, gcc 3.4 and gdb 6.8
Edit | Attach | Watch | Print version | History: r6 < r5 < r4 < r3 < r2 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r6 - 2008-10-08 - MarcMagransDeAbril
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    LCG All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright &© 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback