Набор данных огромен по сравнению с кешем, поэтому он будет ограничен кешем памяти.
Использование косвенной адресации усугубит это, поскольку для указателей имеется кэш, а доступ к памяти осуществляется в более случайном порядке, т. Е. Сравнение не с соседями. Программа работает против любых механизмов предварительной выборки в CPU
Рассмотрите возможность разбиения структуры на две структуры в двух массивах.
В качестве эксперимента сравните проход 1 с проходом, где структура только { float val; int idx; };
Если это связано с кэшем и пропускной способностью, это должно иметь существенное значение.
Если ключевым вопросом является локальность кэша, возможно, стоит рассмотреть возможность многофакторного слияния или сортировки в Shell; что-нибудь, чтобы улучшить местность.
Попробуйте отсортировать подмножества размера кэша в записях, затем выполните многофакторную сортировку слиянием (возможно, стоит взглянуть на спецификацию менеджера кэша процессора, чтобы узнать, ясно ли количество ожидаемых попыток предварительной выборки потоков. Опять же, уменьшение размера наборов данных за счет уменьшения размера структур, поступающих из ОЗУ, может быть победителем.
Как получается поле idx? Похоже, это исходная позиция в массиве. Индекс исходной записи?
Если это так, просто выделите второй массив и скопируйте первый во второй:
struct { float val; float val2; int idx } sortedByVal[40000000];
struct { float val; float val2 } sortedbyIdx[40000000];
for (int i=0; i<40000000; ++i) {
sortedbyIdx[sortedByVal[i].idx].val = sortedByVal[i].val;
sortedbyIdx[sortedByVal[i].idx].val2 = sortedByVal[i].val2;
}
Второго сорта нет. Если это так, объедините распределение значения val2 с этим проходом.
Редактировать
Мне было любопытно, что касается относительной производительности, поэтому я написал программу для сравнения функций сортировки «библиотеки» C, qsort, mergesort, heapsort, а также для сравнения сортировки по idx с копией в idx. Он также пересортирует отсортированные значения, чтобы разобраться с этим. Это тоже довольно интересно. Я не реализовывал и не тестировал сортировку Shell, которая часто превосходит qsort на практике.
Программа использует параметры командной строки, чтобы выбрать, какую сортировку и выполнять сортировку по idx, или просто копировать. Код: http://pastebin.com/Ckc4ixNp
Джиттер во время выполнения довольно четкий. Я должен был использовать тактовые частоты процессора, сделать много прогонов и представить лучшие результаты, но это «упражнение для читателя».
Я запускал его на старом MacBook Pro 2,2 ГГц Intel Core 2 Duo.
Некоторые временные характеристики зависят от ОС C.
Сроки (немного переформатированы):
qsort(data, number-of-elements=40000000, element-size=12)
Sorting by val - duration = 16.304194
Re-order to idx by copying - duration = 2.904821
Sort in-order data - duration = 2.013237
Total duration = 21.222251
User Time: 20.754574
System Time: 0.402959
mergesort(data, number-of-elements=40000000, element-size=12)
Sorting by val - duration = 25.948651
Re-order to idx by copying - duration = 2.907766
Sort in-order data - duration = 0.593022
Total duration = 29.449438
User Time: 28.428954
System Time: 0.973349
heapsort(data, number-of-elements=40000000, element-size=12)
Sorting by val - duration = 72.236463
Re-order to idx by copying - duration = 2.899309
Sort in-order data - duration = 28.619173
Total duration = 103.754945
User Time: 103.107129
System Time: 0.564034
ПРЕДУПРЕЖДЕНИЕ : это одиночные прогоны. Для получения разумной статистики понадобится много прогонов.
Код на pastebin фактически сортирует 8-байтовый массив с уменьшенным размером. На первом проходе нужны только val и idx, и поскольку массив добавляется при добавлении val2, в первом массиве нет необходимости в val2. Эта оптимизация заставляет функции сортировки копировать меньшую структуру, а также помещать больше структур в кеш, что хорошо. Я был разочарован тем, что это дает улучшение в qsort на несколько%. Я интерпретирую это как qsort быстро получает куски сортируются по размеру, который помещается в кэш.
Та же самая стратегия уменьшенного размера дает более чем 25% -ное улучшение для порта.
Синхронизация для 8-байтовых структур, без val2:
qsort(data, number-of-elements=40000000, element-size=8)
Sorting by val - duration = 16.087761
Re-order to idx by copying - duration = 2.858881
Sort in-order data - duration = 1.888554
Total duration = 20.835196
User Time: 20.417285
System Time: 0.402756
mergesort(data, number-of-elements=40000000, element-size=8)
Sorting by val - duration = 22.590726
Re-order to idx by copying - duration = 2.860935
Sort in-order data - duration = 0.577589
Total duration = 26.029249
User Time: 25.234369
System Time: 0.779115
heapsort(data, number-of-elements=40000000, element-size=8)
Sorting by val - duration = 52.835870
Re-order to idx by copying - duration = 2.858543
Sort in-order data - duration = 24.660178
Total duration = 80.354592
User Time: 79.696220
System Time: 0.549068
ПРЕДУПРЕЖДЕНИЕ : Это одиночные прогоны. Для получения разумной статистики понадобится много прогонов.