Почему SD * намного медленнее для Ma c, чем Linux? - PullRequest
3 голосов
/ 12 января 2020

Я работаю над однопоточной графической программой, которая выполняет рендеринг с использованием SDL2 . Смотрите в конце меньший пример.

Он работает как на старой машине Linux, так и на несколько менее старой Ma c. Компьютер Linux имеет процессоры 1,60 ГГц, а процессоры Ma c - 2,2 ГГц. Версия SDL для Linux - 2.0.8, а версия SDL для Ma c - 2.0.10. На обоих компьютерах я компилировал с clang++, используя флаги оптимизации -O3 и -flto. Я вызвал исполняемый файл с ./intergrid -fullscreen -pixel-size 3 (по сути, программа заставила меня нарисовать очень много пикселей.)

По какой-то причине медленный компьютер Linux выполнил программу без пота, а Ma c потребовалось несколько секунд, чтобы сделать первый кадр. Ma c был быстрее, чем машина Linux, как и ожидалось, когда я использовал флаг -no-draw для отключения графики.

EDIT: на компьютере Linux есть Intel Haswell Mobile для графики и Ma c перечисляет «Intel Iris Pro 1536 МБ».

Вот минимальный воспроизводимый пример:

#include <SDL2/SDL.h>
#include <stdio.h>

int main(void)
{
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);

    SDL_Window *window = SDL_CreateWindow(
        "Example",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        0, 0,
        SDL_WINDOW_SHOWN);
    SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);

    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);

    SDL_Rect viewport;
    SDL_RenderGetViewport(renderer, &viewport);

    // The screen is not rendered to unless this is done:
    SDL_Event event;
    while (SDL_PollEvent(&event))
        ;

    Uint32 ticks_before = SDL_GetTicks();
    for (int x = 0; x < viewport.w - 10; x += 10) {
        for (int y = 0; y < viewport.h - 10; y += 10) {
            // I just chose a random visual effect for this example.
            SDL_Rect square;
            square.x = x;
            square.y = y;
            square.w = 10;
            square.h = 10;
            SDL_SetRenderDrawColor(renderer, x % 256, y % 256, 255, 255);
            SDL_RenderFillRect(renderer, &square);
        }
    }
    Uint32 ticks_after = SDL_GetTicks();
    printf("Ticks taken to render: %u\n", ticks_after - ticks_before);

    SDL_RenderPresent(renderer);

    SDL_Delay(500);

    // I Won't worry about cleaning stuff up.
}

Я скомпилировал это для Ma c и Linux с clang++ -O3 -flto <filename> -lSDL2. Когда я запустил программу на Ma c, она напечатала:

Ticks taken to render: 849

Программа на Linux напечатала:

Ticks taken to render: 4

Это гигантская разница c!

1 Ответ

2 голосов
/ 14 января 2020

@ keltar нашел решение, которое мне подходит, но они еще не опубликовали его в качестве ответа, поэтому я сделаю это. По какой-то причине металлический бэкэнд SDL2 очень медленный, поэтому решение состоит в том, чтобы использовать бэкэнд OpenGL. Я сделал это, вызвав SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"), если обнаружил, что драйвером по умолчанию был Metal (с использованием SDL_GetRendererInfo.)

...