• Как ускорить этот код(клеточный автомат)?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    В общем смысле, как я вижу по твоему коду, ты вляпался в True Sharing, попутно обмазавшись Cache Misses и окончательно убив свою производительность с помощью неоправданно огромного размера клеток.

    8Б на клетку, состояние которой может поместиться в 1Б, это действительно огромный размер.
    enum CellState : uint8_t уменьшит размер состояния с 4Б до 1Б. А еще этот тип стоит переименовать, т.к. это не CellState, а что-то относящееся к поведению клетки. А вот CellState будет выглядеть так:
    // Renamed from `CellState`.
    enum CellBehavior : uint8_t
    {
        Empty,
        Alive,
    };
    
    struct CellState final
    {
    	CellBehavior	current_behavior : 4;
    	CellBehavior	next_behavior : 4;
    };

    Это позволяет уменьшить размер клетки до 1 байта.

    Данные оперативной памяти процессор подтягивает к себе во внутренний кэш. Кэшей у процессора много и все они связаны. Кэш процессора поделен на линии, работа с которыми синхронизируется между ядрами процессора. Вот именно тут появляется два термина: False cacheline sharing и True cacheline sharing. Если "False", то обрабатываемые разными ядрами данные разделены в разные кэш-линии. Когда "True" - требуемые разным ядрам данные находятся в одной кэш-линии и привет синхронизация. А это ой как медленно.

    В каждом процессоре сегодня сидит гадалка, которая предсказывает какие тебе надо подтянуть данные из RAM в CPU Cache. Выборка из RAM - это довольно долгая процедура, поэтому нужна гадалка чтобы предсказать что судьбой твоего алгоритма предначертано выбрать на следующем этапе. Бывает что гадалка ошибается и тогда твой лагоритм встает в синхронизацию до завершения нужной выборки из памяти. А это - еще медленнее чем синхронизация по кэш-линиям. Это называется промахом по кэшу - cache miss.
    К счастью, это не гадалка виновата в своей ошибке, а ты просто неправильно написал лагоритм. Вот чтобы из лагоритма сделать алгоритм, следует озаботиться чтобы он был более лоялен к гадалке и кэшу процессора.

    Докину еще немного полезной информации.
    Сходи к Адаму Мартину и к Unity, посмотри на парадигму ES/ESP/ECS. Изучи DOD. Попробуй реорганизацию из твоего текущего потока сущностей с полями в потоки полей сущностей. Переделай батчинг обработки клеток так, чтобы данные не синхронизировались между ядрами процессора.
    Возможно тебе еще поможет понимание подхода Out of line, т.к. там хорошо объясняется почему очень большие объекты при их поточной обработке - это не очень дружественно кэшу процессора.
    Еще сюда можно добавить информацию о автоматической векторизации. Это позволит задействовать SIMD инструкции для твоего кода. DOD очень элегантно ложится для обработки твоих клеток SIMD командами.

    Я тут крайне сумбурно накидал, только чтобы дать тебе направления. Кое-чего я даже не написал, но ты обязательно зацепишь все неописанное когда будешь изучать то, что я описал. Думаю, ты уже видишь, в какой объем выльется весь этот материал, если писать его в удобном понятном формате и раскрывая каждую тему.
    Ответ написан
    Комментировать
  • Почему все так рьяно говорят о том, что C++ ужасен и не нужен, но при этом он стабильно входит в топ 10 яп?

    32bit_me
    @32bit_me
    Программист, встраиваемые системы
    Есть всего два типа языков программирования: те, на которые люди всё время ругаются, и те, которые никто не использует.

    © Бьерн Страуструп
    Ответ написан
    Комментировать
  • Почему данный код не срабатывает?

    wisgest
    @wisgest
    Не ИТ-специалист
    Массив в выражении является указателем на свой 0-й элемент. Это то же самое, если бы в условии было &Name[0] == &Surname[0] — указатели указывают на разные адреса.
    Ответ написан
    Комментировать
  • Как работает это выражение в Си?

    @res2001
    Developer, ex-admin
    Работает в Си так же как в С++.
    Тут надо немного теории:
    Как мы обычно индексируем массив: array[2]
    Компилятор это дело приводит к виду: *(array + 2)
    А теперь, что будет если написать вот так: *(2 + array)?
    Все нормально будет, результат тот же. При этом такое выражение, если переписать в индексном виде будет иметь вид: 2[array]
    Все остальное в приведенном варианте printf - декорация для запудривания мозгов - обычная операция ,
    Ответ написан
    Комментировать
  • Что может быть в Сайте под названием "Форм идей"?

    Zoominger
    @Zoominger Куратор тега Веб-разработка
    System Integrator
    я хочу создать сайт где делятся идеями в ИТ сфере как вы думайте что там может быть что можно добавить?

    Абсолютно ничего.
    Всё уже сделано до вас.
    А если не сделано, то никому и не нужно.
    Ответ написан
  • В чём отличие между char* и char[]?

    32bit_me
    @32bit_me
    Программист, встраиваемые системы
    Разница в том, что в первом случае компилятор видит, что строковые литералы одинаковы, и генерирует только одну строку, и присваивает str1 и str2 указатели на неё. Во втором случае он не может так сделать, потому что массивы не константны, и в дальнейшем могут изменяться независимо. Поэтому указатели разные.
    Однако в общем случае поведение такого кода полностью зависит от реализации компилятора и от опций, поэтому лучше так не делать вообще. Clang пишет: array comparsion always evaluates to false.
    Ответ написан
    5 комментариев
  • Почему нужно перед переменной ставить тип переменной?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    Ответ написан
    Комментировать
  • Инвертировать определенные биты в числе?

    devalone
    @devalone
    ̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻
    xor с маской, где установить все биты в 0, а те, что надо инвертировать, в 1. Ах, да, для читабельности, используй бинарный литерал https://en.cppreference.com/w/cpp/language/integer...
    Ответ написан
    Комментировать
  • Как сделать массив произвольной длины?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как быть? Какой размер массива объявить?

    Не объявляй никакой. Воспользуйся вместо этого стандартным контейнером, например std::vector.
    Но если хочется помучаться -- воспользуйся указателем и выделяй память динамически, по мере поступления входных данных.
    Ответ написан
    Комментировать
  • Как линковщик производит подстановку функций из динамических библиотек?

    @Mercury13
    Программист на «си с крестами» и не только
    Это называется name mangling — как по-русски, я не знаю, но называю это «козявить имена».

    Названия foo в объектных файлах действительно не будет существовать.

    Линкер тут ни к чему, имена готовит компилятор. Потому, кстати, в межъязыковых библиотеках стараются имена не козявить.

    Чтобы функция называлась именно так, как надо, в Си++ есть ключевое слово extern "C", и часто его применяют, например, при экспорте в межъязыковой DLL, при интеграции Си-кода с Си++. Что в Ди, не знаю.
    В Си такого точно нет, как ты назвал, так и называются.

    Линкер, конечно, может каким-то образом подхватывать DLL (так работает LD), но это очень не стандартно — при переходе с LD на LLD пришлось готовить *.a для всех имеющихся DLL. Но в любом случае именами занимается компилятор.
    Ответ написан
    4 комментария
  • Почему данные не записываются в реестр?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    LONG error = RegCreateKeyEx(...);
      if (hKey) {

    Ошибок нет, но и результатов нет !

    Ошибок нет, потому что ты не проверяешь код ошибки, а вместо этого проверяешь hKey.
    Если внимательно прочитать https://docs.microsoft.com/en-us/windows/win32/sys... то можно увидеть для KEY_WOW64_32KEY, что
    This flag must be combined using the OR operator with the other flags in this table that either query or access registry values.

    Подозреваю, что там должно быть KEY_WOW64_32KEY | KEY_SET_VALUE.

    RegSetValueA(hKey, "test", REG_SZ, (LPCSTR)path.c_str(), sizeof(path.c_str()));

    Не sizeof. И код ошибки тоже не проверяешь.
    Ответ написан
  • Как сохранить в памяти и суммировать в число определенную в байтах массу файлов а затем использовать результат?

    @res2001
    Developer, ex-admin
    Из mass() возвращайте размер файла. Там где вызываете mass() суммируйте возвращенное значение.
    unsigned mass(char filePath[]) {
       ...
      return fileSize;
    }
    ...
    unsigned sum_mass = 0;
    sum_mass += mass("file1.txt");
    sum_mass += mass("file2.txt");


    Если сделать sum_mass глобальной, то она будет видна из всех функций данной единицы трансляции. И можно ее присваивать непосредственно в mass() и возвращать в endSumm(). Кстати endSumm() у вас не правильно объявлена.
    Но я бы не советовал использовать глобальные переменные - плохая практика.
    Ответ написан
    Комментировать
  • Почему ArrayList итерируется быстрее, чем LinkedList?

    tsarevfs
    @tsarevfs
    C++ developer
    ArrayList практически(*) всегда быстрее чем LinkedList. Это связано с тем, что ArrayList хранит данные в непрерывном куске памяти. LinkedList же выделяет память для каждого узла и связывает их ссылками.
    Современные процессоры хорошо работают с непрерывными данными. Это связано с работой кэша и суперскалярной архитектурой. Процессор может подгружать данные наперед, использовать векторные SSE инструкции и.т.д.
    https://habr.com/en/post/312078/
    В LinkedList каждая итерация вероятно приведет к обращению к памяти. Для массива это увеличение счетчика в регистре процессора. Разница по времени может достигать сотен раз.

    *LinkedList асимптотически(при достаточно большом размере) быстрее при вставке и удалении элементов из средины, поскольку для массива нужен сдвиг элементов. Однако это можно заметить только на массивах с сотнями а то и тысячами элементов.
    Ответ написан
    2 комментария
  • Книги, советы, курсы по архитектуре приложений?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Начните с хрестоматийного трёхтомника Роберта Мартина "Чистый код", "Чистая архитектура" и "Идеальный программист".
    Ответ написан
    Комментировать
  • Почему деструктор крашится на чистке и-ого элемента?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    У тебя в классе massiv нет конструктора копирования, а аргументы методам sum и multiply ты передаёшь по значению. Это значит, что при создании копий объектов класса massiv память не выделяется, но при их уничтожении она освобождается. А потом освобождается повторно при удалении оригинальных объектов. Поэтому не работает.
    Самый простой фикс -- поменять

    void massiv::sum(massiv obj1, massiv obj2)
    void massiv::multiply(massiv obj1, massiv obj2)

    на

    void massiv::sum(const massiv& obj1, const massiv& obj2)
    void massiv::multiply(const massiv& obj1, const massiv& obj2)
    Ответ написан
    2 комментария
  • Нормально ли изучать android разработку по startandroid?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    Ненормально ничему обучаться ни по каким курсам. Учебники и официальная документация - единственное качественное и действенное средство.
    Ответ написан
    4 комментария
  • Головоломки помогают айтишникам улучшить мышление?

    Adamos
    @Adamos
    Головоломки ставят перед человеком задачи, у которых заранее не известно решение.
    Они развивают как логику, так и умение решать задачи, а главное - вырабатывают привычку решать их и получать от этого удовольствие, а не скатываться в "я гуманитарий и у меня лапки".
    Так что они полезны любым людям, которые работают головой - в том числе и тем, чьи айтишные профессии требуют такой работы.
    Ответ написан
    1 комментарий
  • Небольшая задача из книги Страуструпа. Как её решить?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Условие правильное, просто наверное перевод немного странный.
    Программа и выведет возраст в месяцах. Однако, если пользователь введёт не целое число лет, например 5,5, а вы сохраните результат в целочисленную переменную, то вы потеряете полгода, или 6 месяцев. Программа наглядно это демонстрирует. Просто попробуйте использовать для хранения введённых данных сначала int, а потом double и посмотрите на результат, после ввода 5,5 в обоих случаях. Упражнение нацелено как раз на это.
    Ответ написан
    Комментировать