Ответы пользователя по тегу Многопоточность
  • Что планирует ОС - потоки или процессы?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Из всего изученного стало понятно, что процессы - это некие "контейнеры", содержащие id, статус, instruction pointer, значение регистров, открытые файлы и другие данные контекста.

    Вот уже по этому предложению видно, что понятно не стало. instruction pointer и значения регистров -- свои у каждого потока.

    какую роль в планировании играют процессы?

    Никакой.

    Для чего они нужны?

    Для учёта ресурсов и создания изолированных адресных пространств.

    Как планировщик ОС работает с процессами?

    Никак.

    Моя единственная догадка в том, что планировщик как бы "заглядывает" в каждый процесс и уже там работает с потоками.

    Не нужно ему никуда заглядывать. У него есть списки потоков находящихся в разных состояниях, а планирование заключается в перемещении потоков по этим спискам.
    Ответ написан
    9 комментариев
  • Как узнать, откуда прерывание?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    проблема заключается в том, что я не знаю, как получить состояние машины в момент прерывания, чтобы его сохранить.

    Возможно тебе следует выяснить, что это конкретно за "состояние машины" которое ты собираешься сохранить, возможно это поможет тебе его найти.
    Ответ написан
    4 комментария
  • Как лучше сделать параллельный for?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В чем между ними разница и где какой предпочтительно использовать

    В том, что std::for_each -- это алгоритм из стандартной библиотеки C++, а tbb::parallel_for -- это часть intel Threading Building Blocks. Если проект не использует TBB, то выбор очевиден. Если использует, то у tbb::parallel_for несколько больше возможностей по управлению разбиением интервала на части и выполнением рабочих потоков.
    Ответ написан
  • Как исправить ошибку "Кадр не находится в модуле" при создании потока?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    "Кадр не находится в модуле". Подскажите с чем это может быть связано
    HANDLE h = CreateThread(
        NULL,
        0,
        factorial(gn),
        NULL,
        NULL,
        NULL
    );

    Третий параметр CreateThread -- указатель на функцию, которая будет запущена в создаваемом потоке. А у тебя записано скорее всего что-то другое. Если ты хотел запустить функцию factorial в потоке, она должна 1) иметь определённый прототип (вот такой), и 2) в функцию CreateThread надо передать её адрес, а не результат её вызова (например, так: CreateThread(NULL, 0, factorial, NULL, NULL, NULL)). 3) если ты сделаешь эти два изменения, тебе прийдётся также переделать передачу параметра в функцию factorial и получение результата её работы.
    Ответ написан
  • Как продолжить выполнение кода, не дожидаясь завершения потока?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    типа того:
    #include <iostream>
    #include <thread>
    #include <vector>;
    
    using namespace std;
    
    void go(int p) {
      while (1) {
        cout << p << endl;
      }
    }
    
    void main() {
      thread *t[3];
    
      for (int i = 0; i <= 2; i++) {
        t[i] = new thread(go, i);
        cout << 123;
      }
      for (int i = 0; i <= 2; i++) {
        t[i]->join();
        delete t[i];
      }
    }
    Ответ написан
    Комментировать
  • Что такое Потоки на уровне ОС? В 1-ядерном процессоре же всего 1 поток?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    И К примеру выполняется такие команды, как пример инструкция чтения строки из stdin, почему вся ос не глохнет. Типа что в этот момент ожидания времени происходит, Или что ОС все 1000 потоков переключает там каждую 0.0001 секунды?

    Только готовые к выполнению потоки получают процессорное время. Потоки могут останавливаться в ожидании какого-либо примитива синхронизации, например семафора или мьютекса. Такие потоки не занимают процессор.
    Поток читающий из stdin может останавливаться, например, на семафоре, защищающем очередь данных stdin когда она пуста. Какой-то другой поток должен поместить новые данные в очередь stdin и открыть этот семафор, переведя ожидающий поток в состояние готовности к выполнению.
    Ответ написан
    Комментировать
  • Корректно ли из разных потоков вызывать одну и ту же функцию?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    это нормальная практика, или может быть какая ошибка в случае, когда 2 объекта А одновременно вызывают метод из Б?

    Зависит от того как устроен и куда обращается этот метод. Если он прямо или косвенно обращается к изменяемым глобальным данным без синхронизации или использования атомарного доступа -- может быть ошибка.

    Например, обращение к любой из переменных global/class_static/function_static в следующем коде -- потенциальная ошибка:
    int global;
    
    class B
    {
        static int class_static;
    public:
        void f()
        {
            static int function_static;
        }
    };
    Ответ написан
  • Есть ли какие-нибудь паттерны или фрейворки для программирования под многоядерные ARMы?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Есть ли какие-нибудь ... технологии в языках, ориентированные на многоядерность?

    OpenMP.
    Ответ написан
    Комментировать
  • Насколько хорошим решением является использование pthread_kill для возобновления работы потоков?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Насколько хорошим решением является использование сигналов для выведения потоков из спящего режима, и стоит ли для этого использовать ...

    Является решением, но не самым традиционным. Насколько хорошим -- зависит от модели совместной работы потоков/того как разделяются данные между ними. Не хватает контекста для ответа.
    Ответ написан
  • Как правильно прервать поток в Си?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Общее правило при работе с потоками, не специфичное для С или pthreads: состояние резделяемое между потоками должно быть или атомарным или должно быть защищено примитивом синхронизации.
    Код функции thread_process никак не гарантирует, что компилятор не выкинет проверку !quit, потому что quit не меняется в этой функции и в функциях вызываемых из неё.

    Учитывая, что атомарность и потоки вошли в стандарт С11 имеет смысл смотреть туда.
    Если С11 недоступен, смотреть в pthread_mutex_*, pthread_cond_*, ...

    Может стоит вынести флаг в параметры потока

    По-хорошему -- да, стоит. Это, однако, ортогонально к синхронизации доступа.

    while(!quit) {
            if(difftime(time(NULL), last_cycle) > 30) {
                last_cycle = time(NULL);
                // Тут мои грязные дела
            }
        }

    Вместо busy wait лучше использовать sleep или что-нибудь типа pthread_mutex_timedlock/pthread_cond_timedwait.

    Я бы оформил код этого примера так:
    #include <sys/time.h>
    #include <pthread.h>
    #include <stdbool.h>
    #include <string.h>
    #include <stdio.h>
    
    struct thread1 {
        pthread_mutex_t lock;
        pthread_cond_t cond;
        bool quit;
    };
    
    static void* thread_process(void *p) {
        struct thread1 *arg = p;
    
        for (;;) {
            bool quit;
    
            pthread_mutex_lock(&arg->lock);
            if (!arg->quit) {
                struct timeval now;
                struct timespec ts;
    
                gettimeofday(&now, NULL);
                ts.tv_sec = now.tv_sec + 30;
                ts.tv_nsec = now.tv_usec * 1000;
                pthread_cond_timedwait(&arg->cond, &arg->lock, &ts);
            }
            quit = arg->quit;
            pthread_mutex_unlock(&arg->lock);
            if (quit)
                return NULL;
    
            // Тут мои грязные дела
        }
        return NULL;
    }
    
    int main() {
        pthread_t th;
        struct thread1 arg = {
            .lock = PTHREAD_MUTEX_INITIALIZER,
            .cond = PTHREAD_COND_INITIALIZER,
            .quit = false,
        };
        pthread_create(&th, NULL, thread_process, &arg);
    
        char cmd[16];
        while(true) {
            scanf("%s", cmd);
            if(!strcmp(cmd, "quit")) {
                pthread_mutex_lock(&arg.lock);
                arg.quit = true;
                pthread_cond_broadcast(&arg.cond);
                pthread_mutex_unlock(&arg.lock);
                break;
            }
            // остальные команды
        }
    
        pthread_join(th, NULL);
        return 0;
    }
    Ответ написан
    1 комментарий
  • Как java поток выбирает ядро процессора?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как я понял, ядра имеют доступ только к своему L1 кэшу, а если поток будет исполняться на другом ядре, то он не увидит свои объекты, которые находятся в кэше другого ядра
    Я правильно мыслю?

    Нет. Все системы поддерживающие SMP имеют когерентный кеш. Т.е. если ядро обращается к данным, находящимся в L1 кеше другого ядра, то данные перемещаются в кеш запрашивающего ядра. См.
    Ответ написан
    Комментировать
  • Ошибка undefined reference to `pthread_create'. Как исправить?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    make -j1 -lpthread

    - вместо -lpthread лучше писать -pthread
    - опцию -pthread нужно передавать не make а gcc
    Ответ написан
    8 комментариев
  • Почему std::thread не работает без вызова std::cout?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Не могу понять, почему у меня не отрабатывает std::thread без вызова cout? Как такое вообще возможно?

    А в ассемблер-то не заглянуть никак? Я вижу, что всё отрабатывает, что с cout, что без, что с -O0, что с -O2.
    Ответ написан
  • Как убрать IRQ системного таймера для потока приложения или ядра CPU?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Есть есть поток, который добровольно не отдает управление ЦП и не должен.
    nonvoluntary_ctxt_switches: 68267288

    Этого недостаточно. Нужно чтобы кроме этого потока на данном CPU не было других. ctxt switch это переключение с одного потока на другой.

    Проблема в том, что системный таймер присылает прерывание LOC (Local timer interrupts) 1000 раз в секунду.

    Похоже, что у вас ядро с обычными тиками (не dyntick / tickless). Само таймерное прерывание, однако, не должно заметно влиять на производительность.

    Я бы не хотел манипулировать таймером вообще, или собирать ядро со специальными опциями

    Думаю, что вариантов без сборки ядра с опцией CONFIG_NO_HZ_FULL нет. Но и в этом случае, чтобы не было nonvoluntary ctxt switch на данном CPU должен быть единственный поток. См. https://www.kernel.org/doc/Documentation/timers/NO...
    Ответ написан
  • POSIX threads + usleep - почему не работает?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    usleep имеет код возврата и устанавливает errno в случае ошибки. Воспользуйтесь этим.
    Ответ написан
    Комментировать
  • Как один сетевой сокет обрабатывает много соединений?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Выходит, что на стороне сервера все запросы маршрутизируются через один серверный сокет, забинденый на порту? Как происходит маршрутизация?

    Через серверный сокет проходят только запросы на установку соединения. После того как соединение установлено, на стороне сервера создаётся новый сокет, связывающий IP сервера на которым был принят запрос, порт сервера, IP клиента, отправившего запрос и порт клиента. Этого набора информации достаточно, чтобы определить, что пришедший пакет должен появиться в этом сокете, а при записи в сокет понять, куда отсылать пакет.
    Ответ написан
    3 комментария
  • Можно ли pThread поставить в состояние паузы из другого потока?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В pthreads нет одной переносимой функции для того, что вы хотите сделать. Первую часть (поставить на паузу другой поток по его ID) можно реализовать с помощью сигналов, вторую (чтобы после создания поток был в состоянии паузы) -- с помощью примитивов синхронизации.
    Поиск по слову pthread_suspend выведет вас на возможные реализации.
    Ответ написан
  • Как вызвать C++ метод класса, callback из библиотеки на C?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Насколько я помню, wxWidgets не умеет обрабатывать вызовы функций из других потоков.
    Скорее всего это не проблема взаимодействия C и C++. Для уверенности запустите приложение в gdb и покажите стектрейс в момент получения сигнала.
    Ответ написан
    Комментировать
  • Почему не работает распараллеливание потоков в gcc?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    for (i = 0; i < T; i++)
            for (j = 0; j < T; j++);

    На таком тестовом примере работу оптимизатора не увидеть никогда, потому что при -O0 оптимизатор не запускается, а при -О1,2,3 этот цикл будет выкинут целиком и заменён на i = T, j = T.
    Ответ написан
    1 комментарий
  • Как осуществить многопоточный запуск программ в linux на си?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    //костыли для ожидания окончания работы процессов, чтобы не возиться с мьютексами и семафорами

    Достаточно вызвать pthread_join для каждого из запущенных потоков.

    fclose(f); //после того, как прочитали закрываем программу

    Должно быть pclose(f).

    id--; //минусуем счётчик потока

    Зря вы так, грязными руками в общую переменную.

    Из чего можно заключить: потоки и программы выполняются ПОСЛЕДОВАТЕЛЬНО

    Non sequitur. Но для полноты картины хотелось бы увидеть Makefile.
    Ответ написан
    1 комментарий