Да, вы можете. Вы спросили об изменчивом случае, но я предоставлю, сказав, что если только Vec
(например, для уменьшения), вы можете безопасно отправлять неизменяемую ссылку на определенный фрагмент, который вы хотите в каждом потоке. Вы можете сделать это, просто используя что-то вроде &my_vec[idx1..idx2]
в цикле.
Для изменчивого футляра это немного сложнее, поскольку трекер записи недостаточно изощрен, чтобы позволить неперекрывающимся заимствованиям Vec
. Однако существует ряд методов, в частности split_at_mut
, которые вы можете позвонить, чтобы получить эти объекты. Самым простым является итератор chunks_mut
, зарегистрированный here. (Обратите внимание, что существует итератор соответствия chunks
для неизменяемого случая, поэтому вам нужно лишь внести незначительные изменения при записи любого случая).
Имейте в виду, что chunks
и chunks_mut
функции принимают размер каждого куска, а не количество кусков. Однако вывод одного из другого достаточно прост.
Я хотел бы дать несколько слов предостережения с изменчивым случаем. Если вы разделите данные равномерно, вы можете получить ужасную производительность. Причина в том, что ЦП не работает на отдельных адресах, вместо этого он работает с блоками памяти, известными как строки кеша длиной 64 байта. Если несколько потоков работают в одной строке кеша, они должны писать и читать медленную память, чтобы обеспечить согласованность между потоками.
К сожалению, в надежной русте нет простого способа определить, где в строке кэша запускается буфер Vec
(поскольку запуск буфера, возможно, был выделен в середине строки кэша ЦП), большинство методов I знать, чтобы обнаружить это, включают слияние с нижними байтами фактического адреса указателя. Самый простой способ справиться с этим - просто добавить 64-байтовый блок бессмысленных данных между каждым фрагментом, который вы хотите использовать. Так, например, если у вас есть Vec
, содержащий 1000 32-битных поплавков и 10 потоков, вы просто добавляете 16 поплавков с фиктивным значением (поскольку 32-бит = 4 байта, 16 * 4 = 64 = 1 кэш-строка) между каждый 100 ваших «реальных» поплавков и игнорирует манекены во время вычислений.
Это известно как ложное разделение, и я призываю вас найти другие ссылки, чтобы узнать другие методы борьбы с этим.
Обратите внимание, что размер в 64 байта гарантирован на архитектуре x86. Если вы компилируете ARM, PowerPC, MIPS или что-то еще, это значение может и будет меняться.
Поиск в Интернете для «ржавчины vec thread» приводит к http://stackoverflow.com/q/28599334/155423; http://stackoverflow.com/q/31644152/155423; http://stackoverflow.com/q/33818141/155423; и многие другие. Обязательно сделайте свое [усилие и проявите это усилие при задании вопроса] (http://meta.stackoverflow.com/q/261592/155423). – Shepmaster
@Shepmaster спасибо – MaxB