1

I have to read a binary file which contains 1300 images of 320*256 of uint16 pixels and convert this to a 3D array. The data is saved with little-endian mod so I read 2 bytes in a char and convert it into a double (to do some operation with it after). The saved data is on the following pattern:

Main header / Frame header1 / Frame1 / Frame header2  / Frame2 / etc.

Sorry I can't give you the file. My actual C++ code is :

EDIT : new version which take 4 seconds instead of 21

#include "stdafx.h"
#include <iostream>
#include "stdio.h"
#include <fstream>
#include <stdint.h>

using namespace std;

// Create a function to convert any size of data in little-endian mod
template<class T>
T my_ntoh_little(unsigned char* buf) {
    const auto s = sizeof(T);
    T value = 0;
    for (unsigned i = 0; i < s; i++)
        value |= buf[i] << CHAR_BIT * i;
    return value;
}

int main()
{
    ifstream is("Filename", ifstream::binary);
    if (is) {
        // Create 3D array to stock images
        unsigned char data_char[2];
        double ***data;
        data = new double**[1299];
        for (unsigned i = 0; i < 1299; i++) {
            data[i] = new double*[256];
            for (unsigned j = 0; j < 256; j++)
                data[i][j] = new double[320];
        }

        // Pass main header
        is.seekg(3000, is.beg);

        // Read all data once
        is.read(reinterpret_cast<char*>(data_char), length);

        // Convert pixel by pixel from uchar to double
        int buffer_image = width * height * 2;
        int indice;

        for (unsigned count = 0; count < count_frames; count++) {
            indice = main_header_size + count * (frame_header_size + buffer_image) + frame_header_size;
            for (unsigned i = 0; i < 256; i++){
                for (unsigned j = 0; j < 320; j++) {
                    data[count][i][j] = my_ntoh_little<uint16_t>(data_char + indice);
                    indice += 2;
                }
            }
        }

        // De-Allocate memory to prevent memory leak
        for (int i = 0; i < 1299; ++i) {
            for (int j = 0; j < 256; ++j)
                delete[] data[i][j];

            delete[] data[i];
        }
        delete[] data;

    }
    return 0;
}

I already create a memory map in Python to read this file but in C++ I don't find how to achieve this goal. I try to do this because at now I need 21 seconds to read the file which is very long. I know in Python the reading with a memory map is under 0.1 seconds. I am looking for a solution equivalent, just faster than my actual way which is very too slow.

Code Python :

dt = [('headers', np.void, frame_header_size), ('frames', '<u2', (height, width))]
mmap = np.memmap(nom_fichier, dt, offset=main_header_size)
array2 = mmap['frames']

I thank you in advance for any advice/help.

Mathieu Gauquelin
  • 601
  • 11
  • 35
  • You can probably make use of [boost memory mapped files](http://www.boost.org/doc/libs/1_66_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_file). – G.M. Jan 30 '18 at 09:25
  • might help: https://stackoverflow.com/questions/41480184/what-is-the-functionality-of-munmap-mmap – PiotrNycz Jan 30 '18 at 09:27
  • Have you tried to run a profiler? I suspect the nested allocations could slow you down quite a bit. Also the comparison with the Python code is not really fair because memmaps load data on demand and i'm not sure if accessing `mmap['frames']` is enough to actually pull in data. – MB-F Jan 30 '18 at 09:44
  • 2
    In general, if you need to load all the data and you have enough RAM, memmaps won't give you much benefit. – MB-F Jan 30 '18 at 09:45
  • It is because Visual Studio limits RAM used at 1Go so I am limited by this now – Mathieu Gauquelin Jan 30 '18 at 10:31
  • 1
    Is it a typo, or do you actually allocate 1299 elements to later process 1300 of them??? That would invoke undefined behaviour which can do anything including wasting time... In addition you repeatedly call `my_ntoh_little` that you haven't shown. Anyway, 21 seconds to load 200Mb from disk is not that much. Python code returns in 0.1 second because mmap only opens the file and setups structures but does not load anything in memory. – Serge Ballesta Jan 30 '18 at 10:40
  • Yes I have 1300 images in my file. And I have to work with it (mean, substract, etc) so I have to get all images before to work. And ok thank you for your thought about the time. My function `my_ntoh_little` is on my post. – Mathieu Gauquelin Jan 30 '18 at 10:57
  • 1
    Actually HDD reading speed is typically about 100 MB/s and SSD reading speed is typically about 400 MB/s. So on one hand **nothing** can read 200 MB with 0.1 s and on the other hand reading so well structured data much longer than with 3 sec from hard drive using ifstream just demonstrates that your algorithm is crap and the 15% difference (that mmap and fstream may have) does not improve it. – Öö Tiib Jan 30 '18 at 14:12
  • If I post here it is exactly because I am a beginner in C++ to read file, and begin with such example is not easy. Ok my algorithm is crap but at now it is the best I can do by myself. – Mathieu Gauquelin Jan 30 '18 at 15:26

0 Answers0