qsort_b и qsort

Написание программы, демонстрирующей другой алгоритм сортировки на C++ на Mac. Я нашел две реализации быстрой сортировки, qsort и qsort_b.

Первый, конечно же, старомодный, вездесущий qsort. Но есть qsort_b, который принимает блок, а не функцию. Вот мой код:

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstdio>
#include <ctime>

#define DATA 1000000

using namespace std;

int compare(const void* a, const void* b)
{
    return *(int*)a - *(int*)b;
}

int main(int argc, char *argv[])
{
    int* array = new int[DATA];

    srand(time(0));

    for ( int i = 0 ; i < DATA ; ++ i )
    {
        array[i] = rand() % 2147483647;
    }

    clock_t begin = clock();

    qsort(array, DATA, sizeof(array[0]), compare);
    //qsort_b(array, DATA, sizeof(array[0]), ^(const void* a, const void* b) { return *(int*)a - *(int*)b; });

    clock_t end = clock();

    cout << "Time it takes to sort " << DATA << " integers with quicksort: " << end - begin;
}

Здесь я вижу большую разницу в скорости, из-за чего вся эта разница. Насколько я понимаю, блоки предназначены для параллельной обработки, которая в этом случае не будет быстрее, чем функции. Параллельный процесс не к чему, не так ли?

РЕДАКТИРОВАТЬ: подпрограммы heapsort_b(), mergesort_b() и qsort_b() похожи на соответствующие подпрограммы без суффикса _b, ожидайте, что обратный вызов сравнения является указателем блока, а не указателем функции. (С СТРАНИЦЫ BSD MAN)

EDIT: разница в скорости. При значении DATA 1000000 qsort закончил его за 146832 нс, а qsort_b — за 127391 нс. Это относительно большая разница, учитывая, что он примерно на 10% быстрее.

РЕДАКТИРОВАТЬ: я отредактировал код, чтобы можно было иметь еще больший массив целых чисел. Мой личный самый большой результат теста: 100000000 целых чисел, 28136278 (28 с) против 23870078 (24 с). Для меня это довольно большая разница.


person Shane Hsu    schedule 17.12.2012    source источник
comment
можете уточнить большую разницу в скорости   -  person Karthik T    schedule 17.12.2012
comment
@KarthikT Я не уверен в единицах измерения, но думаю, что это наносекунды. С qsort это 146832, с qsort_b это 127391. С DATA 1000000.   -  person Shane Hsu    schedule 17.12.2012
comment
Я тестировал его с еще большими данными, 100000000 целых чисел. Это 28136278 (28 с) против 23870078 (24 с). Для меня это довольно большая разница.   -  person Shane Hsu    schedule 17.12.2012
comment
Кажется, это нестандартный function, потому что это было единственное упоминание об этом qsort_b.   -  person Rapptz    schedule 17.12.2012
comment
@Rapptz Вы правы, это нестандартно и появляется только на моем Mac. Я могу найти ссылку на него в руководстве BSD по ссылке, которую я предоставил.   -  person Shane Hsu    schedule 17.12.2012
comment
Блоки очень похожи на anonymous functions — их можно моделировать с помощью макросов, которые генерируют код во время компиляции. В этом примере блок служит inline function - поэтому вы получаете увеличение скорости, потому что в каждом сравнении строк процессор экономит время на вызовы функции сравнения.   -  person Agnius Vasiliauskas    schedule 17.12.2012
comment
@ 0x69 Спасибо за объяснение.   -  person Shane Hsu    schedule 18.12.2012
comment
@ 0x69 Я не думаю, что блоки можно моделировать с помощью макросов - блоки можно передавать в скомпилированные библиотечные функции, которые не имеют доступа к источнику вызывающего объекта и, следовательно, не могут расширять макрос. То же самое относится и к такой функции, как qsort_b — вызов может быть быстрее, но истинное встраивание невозможно, так как сама qsort_b уже скомпилирована.   -  person user4815162342    schedule 20.10.2013
comment
Как вы думаете, что делает rand() % 2147483647 в отличие от обычного вызова rand()? Кроме того, ваше время указано в единицах CLOCK_PER_SEC, поэтому общее время составляет (конец-начало)/CLOCKS_PER_SEC секунд. Это зависит от платформы, не обязательно наносекунд.   -  person Klitos Kyriacou    schedule 23.10.2015


Ответы (2)


Objective-C Block — это другой вид животных. Может показаться, что MACRO (подстановка перед компиляцией) и inline functions (сообщение компилятору "Сделайте все возможное, чтобы устранить накладные расходы на вызовы функций"), но общая структура намного отличается от этих структур.

Блок — это объект, более того, объект стека. Единственный объект, который разрешено создавать в стеке (по крайней мере, без всяких ухищрений).

Когда объект Block создается в стеке, компилятор добавляет все локальные переменные, блочные переменные, адреса переменных чтения/записи, на которые он ссылается, и указатель на исполняемый код блока. Таким образом, еще до начала выполнения все готово для вычислений без каких-либо операций со стеком.

Таким образом, это не проблема оптимизации, а атрибут Block. У него нет накладных расходов на вызовы функций PUSH и POP переменных стека.

Как ответ на ваш вопрос, qsort() и qsort_b() не имеют никакой алгоритмической разницы, а имеют продуманную структуру, блок vs функция.

person Cahit Gungor    schedule 23.10.2015

Мне кажется разница в оптимизации. С qsort_b компилятор, вероятно, встраивает сравнение, а с qsort — нет. Разница заключается в накладных расходах на вызов функции на сравнение.

person hyde    schedule 17.12.2012
comment
Вы должны быть правы. Поправьте меня, если я ошибаюсь, в этой конкретной ситуации блоки похожи на встроенные функции. И встроенные функции считаются быстрее, чем функции. (stackoverflow.com/questions/4016061/) - person Shane Hsu; 17.12.2012
comment
@ShaneHsu Я ничего не знаю об этих блоках, кроме того, что я только что прочитал из en. wikipedia.org/wiki/Blocks_(C_language_extension), поэтому не могу комментировать, какой код генерирует для них компилятор. Если вы действительно хотите понять, что происходит, добавьте переключатель командной строки компилятора для создания исходных файлов asm (вместо объектных файлов) для обоих случаев и сравните их. Другой эксперимент может заключаться в том, чтобы попробовать обе версии с отключенными оптимизациями, а затем выкрутить их до максимума и посмотреть, как это повлияет на относительную производительность. - person hyde; 17.12.2012
comment
Потом проведу эксперимент. Спасибо! - person Shane Hsu; 18.12.2012
comment
Если qsort_b является библиотечной функцией, которая существует в системе в скомпилированном виде, я не понимаю, как она может встроить вызов в блок. Может быть, qsort_b просто использует лучший алгоритм сортировки, или блоки имеют немного более эффективное соглашение о вызовах? - person user4815162342; 20.10.2013