Реальный ответ для подобных ситуаций - это кодирование нескольких подходов и определение времени. Что вы, очевидно, сделали. Все, что я могу сделать, это предложить другие подходы.
Например: даже при отсутствии перебора кэша (ваши выходные потоки отображаются в одинаковые строки кэша), если вы пишете размерные целые, с size = 1 << 19 и sizeof (int) = 4, 32-bit То есть, если вы пишете 8 МБ данных, вы на самом деле читаете 8 МБ, а затем пишете 8 МБ. Потому что, если ваши данные находятся в обычной памяти WB (WriteBack) на процессоре x86, для записи в строку сначала необходимо прочитать старую копию строки - даже если вы собираетесь выбросить прочитанные данные. </p>
Вы можете устранить этот ненужный трафик чтения RFO с помощью (a) использования памяти WC (вероятно, проблем с настройкой) или (b) использования потоковых хранилищ SSE, или NT (Non-Temporal) Stores. MOVNT * - MOVNTQ, MOVNTPS и т. Д. (Существует также потоковая загрузка MOVNTDQA, хотя и более болезненная для использования.)
Мне скорее нравится эта статья, которую я только что нашел, прибегая к помощи http://blogs.fau.de/hager/2008/09/04/a-case-for-the-non-temporal-store/
Теперь: MOVNT * применяется к памяти WB, но работает как память WC, используя небольшое количество буферов записи. Фактическое число зависит от модели процессора: на первом чипе Intel их было всего 4, P6 (он же Pentium Pro). Ooof ... Bulldozer 4K WCC (Write Combining Cache) в основном обеспечивает 64 буфера объединения записи на http://semiaccurate.com/forums/showthread.php?t=6145&page=40,, хотя есть только 4 классических буфера WC. Но http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-optimization-manual.pdf говорит, что некоторые процессоры имеют 6 буферов WC, а некоторые 8. Во всяком случае ... есть несколько, но не так много. Обычно не 64.
Но есть кое-что, что вы можете попробовать: реализовать комбинирование записи самостоятельно.
a) запись в один набор из 64 (# потоков) буферов, каждый из которых имеет размер 64B (размер строки кэша), - или может быть 128 или 256B. Пусть эти буферы будут в обычной памяти WB. Вы можете получить к ним доступ в обычных магазинах, хотя, если вы можете использовать MOVNT *, отлично.
Когда один из этих буферов заполнится, скопируйте его как пакет в место в памяти, куда действительно должен идти поток. Использование MOVNT * потоковых хранилищ.
Это в конечном итоге делает
* N байт хранятся во временных буферах, попав в кэш L1
* 64 * 64 байта считываются для заполнения временных буферов
* N байтов считывается из временных буферов, попадающих в кэш L1.
* N байтов, записанных через потоковые хранилища - в основном идут прямо в память.
Т.е. чтение кэша N байтов чтение + попадание кэша N байтов + отсутствие кэша N байтов
в сравнении с отсутствием чтения кэша байтов N + чтение чтения кэша байтов N *
Уменьшение N байтов при чтении из кэша может оказаться более эффективным, чем восполнение дополнительных издержек.