Я пишу простой интросорт на C ++, в котором я пытаюсь вручную развернуть цикл внутри функции секционирования для оптимизации. Программа, которую я включу ниже, компилируется, но не может правильно отсортировать случайный список.
Эта программа компилируется для архитектуры RISC-V, и даже в -Ofast, (riscv-64-unknown-elf-gcc) gcc, по-видимому, не развертывает цикл самостоятельно, делая ручную проверку каждый цикл до конца, чтобы обеспечить выполнение конечного условия. Я хотел бы воспользоваться этой проверкой, чтобы попытаться максимизировать производительность - я понимаю, что некоторые компиляторы в конечном итоге делают это по умолчанию.
Я попытался разбить этот цикл на куски по 5, чтобы доказать концепцию, прежде чем идти дальше (возможно, с несколькими сегментами, например, попробуйте пройти группы по 32, затем попытаться пройти группы по 16 и т. Д.), Затем выполнить последние несколько элементов массива, как у меня ранее. До развертывания программа работала нормально, но теперь сортировка не удалась, и я не уверен, что делать дальше.
Вот функция разбиения:
int* partition(int *startptr, int *endptr) {
int x = *endptr; // threshold
int *j, tmp, tmp2, *i = startptr - 1;
for (j = startptr; j+5 < endptr; j+=5) {
int pj = *j;
if (pj <= x) {
i += 1;
tmp = *i;
*i = pj;
*j = tmp;
}
pj = j[1];
if (pj <= x) {
i += 1;
tmp = *i;
*i = pj;
*j = tmp; }
pj = j[2];
if (pj <= x) {
i += 1;
tmp = *i;
*i = pj;
*j = tmp; }
pj = j[3];
if (pj <= x) {
i += 1;
tmp = *i;
*i = pj;
*j = tmp; }
pj = j[4];
if (pj <= x) {
i += 1;
tmp = *i;
*i = pj;
*j = tmp; }
}
j -= 5;
for (int *y = j; y < endptr; y++) {
int py = y[0];
if (py <= x) {
i += 1;
tmp = *i;
*i = py;
*y = tmp;
}
}
int *incrementedi = i + 1;
tmp = *incrementedi; //p[i+1]
tmp2 = *endptr; //p[end]
*endptr = tmp;
*incrementedi = tmp2;
return i + 1;
}
В конце программы я распечатываю массив и перебираю циклы, утверждая, что все в порядке возрастания, как и ожидалось. Вывод сортируется небольшими порциями, но он не совсем точен, и я не уверен, как поступить. Спасибо!
Редактировать для пояснения: я проверяю, что цикл на самом деле не разворачивается, посмотрев на вывод ...- gcc -S. Функция секционирования прекрасно работает, но все равно выполняет проверку каждой итерации.
Стоит отметить, что я использую указатели всякий раз, когда это возможно, по аналогичной причине - компилятор не оптимизирует для экономии команд, которую мы получаем, когда нам не нужно преобразовывать индексы массива в фактические указатели.