У меня есть функция, которая обрабатывает большое изображение.По спецификации самое большое это изображение может быть 55 МБ.Обработка влечет за собой разбиение изображения на несколько разных полос, а затем воссоздание изображения путем добавления этих полос обратно в выходное изображение.Поскольку изображение очень большое, я не могу сохранить все четыре изображения, а также входные и выходные изображения в памяти одновременно в 32-битной системе.В результате я помещаю каждое изображение на диск, а затем считываю его порциями.
Перед многопоточностью псевдокод выглядит следующим образом:
for (y is 0 to ysize)
unsigned short* ptr1 = ReadLineFromDisk(image1, y)
unsigned short* ptr2 = ReadLineFromDisk(image2, y)
unsigned short* ptr3 = ReadLineFromDisk(image3, y)
unsigned short* ptr4 = ReadLineFromDisk(image4, y)
unsigned short* outPtr = &(outImage[y*inXSize])
for (x is 0 to xsize, ++x, ++ptr1, ++ptr2, ++ptr3, ++ptr4, ++outPtr){
outPtr = combination of ptr1, ptr2, ptr3, ptr4;
}
}
Этот код выполняется за 3 секундыдвухъядерный компьютер со стандартным жестким диском на 500 ГБ, использующий высокопроизводительный счетчик.
Если увеличить число строк, считываемых с диска, примерно до 100, а затем выполнить это с помощью кода, который выглядит следующим образом:
chunksize = 100;
for (y is 0 to ysize by chunksize)
unsigned short* ptr1 = ReadChunkFromDisk(image1, y)
unsigned short* ptr2 = ReadChunkFromDisk(image2, y)
unsigned short* ptr3 = ReadChunkFromDisk(image3, y)
unsigned short* ptr4 = ReadChunkFromDisk(image4, y)
unsigned short* outPtr = &(outImage[y*inXSize])
for (x is 0 to xsize*chunk, ++x, ++ptr1, ++ptr2, ++ptr3, ++ptr4, ++outPtr){
outPtr = combination of ptr1, ptr2, ptr3, ptr4;
}
}
Этот код работает быстрее, чем предыдущий код, до 1,5 секунд.
Вопрос 1. Почему этот код быстрее?
Iпредположить, что это быстрее, потому что, по моему опыту, большие непрерывные чтения быстрее, чем меньшие для того же объема данных.То есть, если я читаю 100 строк данных одновременно, это быстрее, чем 100 отдельных операций чтения, по крайней мере, для обычного (не SSD) жесткого диска.Моя гипотеза близка к правильной?
Несмотря на это, процессор здесь интенсивно не используется.Увеличение размера кеша на самом деле непозволительно, в этом случае 1.5 - лучшее, что я могу получить, а затем значение немного падает (не уверен, почему это тоже будет, за исключением того, что, возможно, какое-то кэширование диска играет роль).Это подводит меня к
Вопрос 2: Почему в размере куска будет сладкое пятно?
Если я здесь что-то понимаю (и я не думаю, что ядействительно, если бы все могло быть в памяти, то это было бы очень быстро, потому что не было бы обращений к диску.Если чтение больше также ускоряет процесс, не будет ли чтение, скажем, четверти изображения за раз, лишь небольшим ударом по скорости?
Итак, я перехожу к размещению внешнего цикла в лямбда-выражении и использованию Intel TBB для потокового кода, что-то вроде:
chunksize = 100;
parallel_for (y is 0 to ysize by chunksize in a lambda expression)
unsigned short* ptr1 = ReadChunkFromDisk(image1, y)
unsigned short* ptr2 = ReadChunkFromDisk(image2, y)
unsigned short* ptr3 = ReadChunkFromDisk(image3, y)
unsigned short* ptr4 = ReadChunkFromDisk(image4, y)
unsigned short* outPtr = &(outImage[y*inXSize])
for (x is 0 to xsize*chunk, ++x, ++ptr1, ++ptr2, ++ptr3, ++ptr4, ++outPtr){
outPtr = combination of ptr1, ptr2, ptr3, ptr4;
}
}
Этот код варьируется в диапазоне скоростей от 0,4 секунд до 1,6 секунд.
Это приводит меня к:
Вопрос 3: не должно ли это увеличение скорости быть не более чем в 2 раза, а не в 4 раза?
Это двухъядерный компьютер, на котором я запускаю эти тесты, поэтомув идеальном мире один поток читает с диска, а другой обрабатывает.Даже когда он работает с четырехкратным увеличением скорости, он использует только 80% процессоров, а не 100%, поэтому узкое место на диске остается.Но увеличение в 4 раза означает, что что-то еще происходит.
Я также предполагаю, что широкий диапазон различий в скорости заключается в том, что потоки не полностью синхронизированы при чтении, если так происходит увеличение скорости.Настоящий, последний вопрос:
Вопрос 4: Как я могу получить последовательное увеличение скорости в 4 раза?