Можно ли заставить несколько процессов python использовать одну и ту же память через расширение C ++? - PullRequest
1 голос
/ 14 июля 2020

Вот моя попытка:

int* globalvar = new int[8];
void cpp_init(){
    for (int i = 0; i < 8; i++)
        globalvar[i] = 0;
}
void writeAtIndex(int index, int value){
    globalvar[index] = value;
}
int accessIndex(int index){
    return globalvar[index];
}
BOOST_PYTHON_MODULE(MpUtils){
    def("cpp_init", &cpp_init);
    def("writeAtIndex", &writeAtIndex);
    def("accessIndex", &accessIndex);
}

и в python файле

def do_stuff(index):
    writeAtIndex(index, randint(1, 100))
    time.sleep(index/10)
    print([accessIndex(i) for i in range(8)])

if __name__ == '__main__':
    freeze_support()
    processes = []
    cpp_init()
    for i in range(0, 10):
        processes.append( Process( target=do_stuff, args=(i,) ) )
    for process in processes:
        process.start()
    for process in processes:
        process.join()

И результат такой:

[48, 0, 0, 0, 0, 0, 0, 0]
[0, 23, 0, 0, 0, 0, 0, 0]
[0, 0, 88, 0, 0, 0, 0, 0]
[0, 0, 0, 9, 0, 0, 0, 0]
[0, 0, 0, 0, 18, 0, 0, 0]
[0, 0, 0, 0, 0, 59, 0, 0]
[0, 0, 0, 0, 0, 0, 12, 0]
[0, 0, 0, 0, 0, 0, 0, 26]

Может кто-нибудь объясните, почему это не работает? Я пробовал напечатать глобальную переменную, и это всегда одно и то же значение. Не должно быть никаких условий гонки, так как ожидания от 0,1 до 0,8 секунды должно быть более чем достаточно, чтобы компьютер что-то написал. Разве C ++ не должен напрямую обращаться к местоположению указателя?

Спасибо

Ответы [ 2 ]

1 голос
/ 15 июля 2020

Процессы обычно имеют доступ только к своему собственному пространству памяти. Вы можете использовать модуль многопроцессорности shared_memory для совместного использования одного и того же массива между процессами. См. Пример на связанной странице.

0 голосов
/ 15 июля 2020

Следующий l oop создаст список процессов с последовательным первым args, от 0 до 9. (Первый процесс имеет 0, второй 1 и т. Д.)

    for i in range(0, 10):
        processes.append( Process( target=do_stuff, args=(i,) ) )

Запись может принимать список чисел, но вызов writeAtIndex будет вызываться с первым элементом только:

def do_stuff(index):
    writeAtIndex(index, randint(1, 100))

Функция writeAtIndex принимает один int, а не список:

void writeAtIndex(int index, int value)

Вот почему ваш результат имеет значение в каждой позиции.

И как сказано в @Voo и в docs :

Пакет multiprocessing предлагает как локальный, так и удаленный параллелизм, эффективно обходя глобальную блокировку интерпретатора, используя подпроцессы вместо потоков.

Объекты процессов представляют собой действия, которые выполняются в отдельном процессе.

Таким образом, для каждого процесса существует globalvar.

Если вы хотите обмениваться данными между потоками, вы можете использовать модуль threading . Однако есть детали, которые вы должны прочитать:

из-за глобальной блокировки интерпретатора только один поток может выполнять код Python одновременно (даже если некоторые ориентированные на производительность библиотеки могут преодолеть это ограничение). Если вы хотите, чтобы ваше приложение лучше использовало вычислительные ресурсы многоядерных машин, рекомендуется использовать multiprocessing или concurrent.futures.ProcessPoolExecutor.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...