Примечание: вопрос претерпел некоторые правки с учетом многочисленных предложений и выводов из комментариев, которые сейчас могут показаться устаревшими. Первоначально он был сосредоточен на количестве потоков, в то время как реальная проблема, похоже, заключается в родстве основных потоков.
(Держу пари, что ваш интуитивный ответ - «синхронизация» - будьте терпеливы, пока я объясняю, почему это не обязательно ответ.)
Приведенный ниже код сравнивает запись одних и тех же данных в файл: по сути, N раз один и тот же фрагмент размером 1 МБ, пока не будет достигнут целевой размер файла в 10 ГБ. . Он делает это с переменным количеством потоков (от 1 до 56), заботясь об одновременном запуске всех потоков и измерении времени, затраченного на вызовы filebuf::sputn.
( Потому что это несколько раз упоминалось в комментариях: цель состоит не в том, чтобы записывать данные быстрее, чем в один поток. Цель состоит в том, чтобы записать данные, сгенерированные в несколько независимых потоков генерации данных, в идеале, не требуя еще одного отдельного потока записи.)< /p>
Ниже вы найдете выходные данные кода, сгенерированного в Windows с использованием MSVC, твердотельного накопителя Samsung MZWL63T8HFLT-00AW7 и процессора Intel Xeon w9-3495X (гиперпоток отключен, отсюда и ограничение на 56 потоков), график которых я построил с помощью https://www.desmos.com/calculator. По сути, вы видите, что если потоки назначены каждый на свое ядро, то время, потраченное на запись файла, зависит от количества потоков, из которых вызывается filebuf::sputn, что я затрудняюсь объяснить, так как блокировка мьютекса исключается из измерения времени записи, а сравнение длительности записи файла и общей продолжительности показывает, что блокировка в любом случае составляет не более 2% от общего времени.
Если все потоки закреплены за одним ядром, проблемы не наблюдается. К сожалению, хотя это может быть решением в этом игрушечном примере, оно неприменимо в реальном сценарии, где каждый поток генерирует свои собственные данные, используя ресурсоемкие операции ЦП.
Это ожидаемое решение результат? Каковы стратегии, позволяющие избежать такой производительности при записи на несколько ядер, кроме, возможно, очевидного (все потоки сбрасывают свои данные в очередь, а отдельный поток очищает очередь и записывает файл)?
Время, затрачиваемое на вызовы filebuf::sputn, в зависимости от количества потоков
синий: каждый поток использует собственное ядро
красный: все потоки используют одно и то же ядро
[img]https://i .sstatic.net/tXF6uFyf.png[/img]
Код
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace chrono;
using double_milliseconds = duration;
int main() {
constexpr auto maxNThreads = 56;
constexpr auto fileSize = 10'000'000'000;
constexpr auto chunkSize = 1'000'000;
mutex mutex;
vector threads;
for (const auto sameCore : {false, true}) {
for (const auto nThreads : ranges::iota_view(1, maxNThreads + 1)) {
filebuf file;
file.open("out.tmp", ios::out | ios::binary);
latch commonStart(nThreads + 1);
streamsize written = 0;
nanoseconds writing{0};
for (const auto i : ranges::iota_view(0, nThreads)) {
const auto threadSize = fileSize / nThreads;
threads.emplace_back([&commonStart, &mutex, &file, &written, &writing, threadSize, sameCore, i] {
const auto mask = static_cast(1)
Подробнее здесь: https://stackoverflow.com/questions/790 ... r-when-wri
Почему многопоточная запись большого файла на SSD медленнее при записи со многих ядер, а не на одно и то же ядро? ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Разделение большого файла CSV и многопоточная загрузка с минимальными затратами
Anonymous » » в форуме C# - 0 Ответы
- 14 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Многопоточная запись TFRecord внезапно прекращается в блокноте Kaggle [закрыто]
Anonymous » » в форуме Python - 0 Ответы
- 7 Просмотры
-
Последнее сообщение Anonymous
-