0

I wanted to create a bit sized variable to save the only possible values 2^1 = 0 | 1

My initial approach was to create a class with variables of type int for storing the value 0 | 1

But then i found that i could also use a bitfield and also create my own struct with custom bits for each type. My question is that does using a struct with bits set to 1 provide better memory performance and hence faster implementation than the class approach for a array of struct like ( 4000 x 4000 )

The code :

#include<iostream>

using namespace std;

struct maze
{
    unsigned int top : 1;
    unsigned int right : 1;
    unsigned int bottom : 1;
    unsigned int left : 1;
};

int main()
{
    maze access;
    
    cout<<sizeof(access);

    access.top=1;
    access.right=1;
    access.bottom=1;
    access.left=1;

    cout<<endl<<sizeof(access);

    return 0;
}

Edit:

I think i have found the answer : https://stackoverflow.com/a/46544000/13868755

  • 2
    Are you aware of `std::bitset`? – Nate Eldredge Sep 04 '20 at 04:39
  • 3
    In general, saving space may or may not result in faster execution, depending on a lot of factors. Modern architectures are *complex*. So are modern compilers. The best way to find out is to *test it*. – Karl Knechtel Sep 04 '20 at 04:43
  • @NateEldredge yes i do, but i also want to learn implementing with it. – theirrevocableSake Sep 04 '20 at 04:50
  • @KarlKnechtel i wonder whether it is possible or not cause since the memory addresses are in bytes, will the program allocate i 1 bit for it or a byte? – theirrevocableSake Sep 04 '20 at 04:52
  • Most likely, the compiler will allocate 1 byte for each `maze` object, of which 4 bits will be used for your bitfield, and the other 4 wasted. Since the machine cannot access memory in smaller units than 1 byte, each access to one of your fields will be done by reading a byte, using logical OR or AND to set or clear the appropriate bit, and writing it back to memory. This is slower than simply writing an entire byte. – Nate Eldredge Sep 04 '20 at 04:56
  • You've missed the compromise in between, which is to use `char` or `bool` instead of `int`. That will at least cost you only 1 byte per value stored, instead of `sizeof(int)` which is typically 4. – Nate Eldredge Sep 04 '20 at 04:57
  • The fastest thing for your machine to operate on is most likely to be a `int`. In any case, you are probably not going to be able to measure any difference in speed between `int` and `bitset` unless you do calculations on the value millions of times each second. Just use what is most convenient, turn on compiler optimizations and don't worry about it. – Jesper Juhl Sep 04 '20 at 04:59
  • @JesperJuhl Let,'s say that i have 5 different variables, each having a value of 1 and 0 each. I was thinking of using the speculated bit sized variables as they could have saved memory as opposed to ints where each of them take 4 bytes. What options do i have? of course other than ( char / bool array ) or should i use something like uint8_t? – theirrevocableSake Sep 04 '20 at 05:18
  • @NateEldredge Let,'s say that i have 5 different variables, each having a value of 1 and 0 each. I was thinking of using the speculated bit sized variables as they could have saved memory as opposed to ints where each of them take 4 bytes. What options do i have? of course other than ( char / bool array ) or should i use something like uint8_t? – theirrevocableSake Sep 04 '20 at 05:19
  • @theirrevocableSake Addressing a single bit would most probably appear more costly (less performant) than addressing a single, well bus aligned `long` in terms of modern CPU architectures. Even with bitfields, the compiler needs to generate all kind of shift and masking assembler code additionally. There are still things like hardware coming in our way, if we believe we can produce _the smarter_ software. – πάντα ῥεῖ Sep 04 '20 at 05:38
  • 1
    @NateEldredge _"Most likely, the compiler will allocate 1 byte for each maze object"_ Nope, that's wrong. The compiler exactly generates what's given as underlying type of the bitfield (`unsigned int` in the OPs case), and unfortunately (but for good reasons), it's not possible to base a bitfield struct on a single byte (i.e. `unsigned char`). – πάντα ῥεῖ Sep 04 '20 at 05:50

1 Answers1

0

This is really hard to speculate about the performance for this case, and there is a fair chance you'll make it work slower.

Unless this is a proven bottleneck, you should focus on writing a readable and testable code. Does the struct storing the four values make the code cleaner? If so, use the struct. Are the values actually boolean, i.e. true or false only? Use bool to make it clear to the reader.

This will be likely just as performant as your current implementation, and take as much space.

For gauging the performance you need a working code to benchmark on, as for the different applications the performance implications will differ, and guessing it beforehand, though a funny thought experiment, isn't really useful in practice.

An exception is when you know you have a lot of data (like, gigabytes) and your are memory constrained. In that case you should indeed focus on the memory over both code readability and CPU usage. In that case going straight to std::bitset would look like a promising option, with good memory usage guarantees and proven correctness.

If memory is only a secondary concern, simply using packed structs/arrays (look for compiler options for that) should be sufficient and way simpler and cleaner to write.

Frax
  • 5,015
  • 2
  • 17
  • 19