SanderMertens / flecs

A fast entity component system (ECS) for C & C++

Home Page:https://www.flecs.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Multi-threaded system inconsistent calculation

Hexlord opened this issue · comments

Describe the bug
Inconsistent system evaluation behavior of multi_threaded system, unpredictable results
Iter.count() is the same
Doint just Count++ inside Iter loop works fine
But this slightly complicated calculation leads to different results based on whether the system is multi_threaded or not, absolute magic

To Reproduce

#include "flecs.h"
#include "inttypes.h"
#include <atomic>
#include <cstdio>

int main() {

  struct Comp1 {
    int field1;
    int field2;
  };

  {
    flecs::world ECS;
    ECS.set_threads(8);

    std::atomic<uint32_t> Count{0};
    ECS.system<Comp1>().multi_threaded(false).iter(
        [&](flecs::iter &Iter) {
          for (auto Index : Iter) {
            auto Entity = Iter.entity(Index);
            (void)Entity;
            for (int I = 0; I < 100000; ++I) {
              Count = Count + 1;
              Count = Count - 1;
              Count = Count + 1;
            }
            Count = Count - 100000 + 1;
          }
        });
    for(int i = 0; i < 100; ++i) {
      ECS.entity().add<Comp1>();
    }
    ECS.progress();
    printf("Single-threaded system: %u\n", Count.load());
  }
  {
    flecs::world ECS;
    ECS.set_threads(8);

    std::atomic<uint32_t> Count{0};
    ECS.system<Comp1>().multi_threaded(true).iter(
        [&](flecs::iter &Iter) {
          for (auto Index : Iter) {
            auto Entity = Iter.entity(Index);
            (void)Entity;
            for (int I = 0; I < 100000; ++I) {
              Count = Count + 1;
              Count = Count - 1;
              Count = Count + 1;
            }
            Count = Count - 100000 + 1;
          }
        });
    for(int i = 0; i < 100; ++i) {
      ECS.entity().add<Comp1>();
    }
    ECS.progress();
    printf("Multi-threaded system: %u\n", Count.load());
  }

  return 0;
}

Expected behavior
/home/sasha/flecs_test/cmake-build-debug/SECore
Single-threaded system: 100
Multi-threaded system: 100

Actual behavior
/home/sasha/flecs_test/cmake-build-debug/SECore
Single-threaded system: 100
Multi-threaded system: 265036 (different every time)

Sorry I am stupid lol, it is read-write op, it is non-atomic :D

This is correct system code and it works correctly

ECS.system<Comp1>().multi_threaded(true).iter(
        [&](flecs::iter &Iter) {
          for (auto Index : Iter) {
            auto Entity = Iter.entity(Index);
            (void)Entity;
            for (int I = 0; I < 100000; ++I) {
              Count++;
              Count--;
              Count++;
            }
            Count.fetch_add(-99999);
          }
        });