Кресты / Говнокод #27074 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
//библиотеки cuda_runtime.h и device_launch_parameters.h
//для работы с cyda
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include<vector>
#include<string>//для getline
#include <stdio.h>
#include<fstream>
using namespace std;
__global__ void Upload_to_GPU(unsigned long long  *Number,unsigned long long  *Stepn, bool *Stop,unsigned long long  *INPUT,unsigned long long  *max) {
	int thread = threadIdx.x;
	unsigned long long  MAX_DEGREE_OF = max[0];
    int X = thread;
	unsigned long long  Calculated_number = 1;
	unsigned long long  Current_degree_of_number = 2;
    unsigned long long   Original_numberP = INPUT[0];
	Stop[thread] = false;
	bool BREAK = false;
	if (X!=0&&X!=1) {
		while (!BREAK) {
			if (Current_degree_of_number <= MAX_DEGREE_OF) {
				Calculated_number = 1;
				for (int counter = 0; counter < Current_degree_of_number; counter++) {
				 Calculated_number	*=X;
				}
				if (Calculated_number == Original_numberP) {
					Stepn[thread] = Current_degree_of_number;
					Number[thread] = X;
					Stop[thread] = true;
					BREAK = true;
				}
				Current_degree_of_number++;
			}
			else { BREAK = true; }
		}
	}
}

https://habr.com/post/525892/
> Сравнение времени выполнения алгоритма на CPU и GPU

Запостил: gost gost, (Updated )

Комментарии (70) RSS

  • Как видно из таблицы, время выполнения алгоритма на GPU немного больше, чем на CPU.
    Однако, отмечу, что вовремя работы алгоритма использующего для вычислений GPU загрузка
    им CPU, в Диспетчере задач, не превышала 30%, в то время как алгоритм использующий для
    вычислений CPU, загружал его на 68-85%, что в свою очередь иногда приводило к замедлению
    других приложений.
    Ответить
    • Стоит отметить, что cyda имеет ограничения по количеству запускаемых потоков,
      поэтому в обоих алгоритмах я взял одинаковое количество потоков, равное 1000.
      Ответить
    • То есть оффлоаднув тяжелые задачи железу можно освободить CPU для пользовательских процессов!

      Какая глубокая мысль
      Ответить
      • Да, особенно это помогает, когда в коде для CPU очень эффективно проводится ожидание конца работы:
        thread *T = new thread[size];
        Running_thread_counter = 0;
        for (int i = 0; i < size; i++) {
            T[i] = thread(Upload_to_CPU, Number, Stepn, Stop, INPUT, max, i);
            T[i].detach();
        }
        while (Running_thread_counter < size - 1);//дождаться завершения выполнения всех потоков


        P. S. Перевёл алгоритм автора на «Python» с «Numba», третий с конца результат, который у него считался 16 секунд, вычислил за 65.
        >>> @numba.jit(nopython=True)
        ... def calc():
        ...     for x in range(2, 1001):  # У него каждый поток проверяет x с собственным номером
        ...         for deg in range(1, 8500):
        ...             if x ** deg == N:
        ...                 yield (x, deg)
        ...
        >>> start = time.time(); res = list(calc()); end = time.time(); print(end - start)
        0.1561572551727295
        >>> res
        [(108, 4)]
        >>> start = time.time(); res = list(calc()); end = time.time(); print(end - start)
        0.06783914566040039
        >>> start = time.time(); res = list(calc()); end = time.time(); print(end - start)
        0.08180832862854004
        >>> start = time.time(); res = list(calc()); end = time.time(); print(end - start)
        0.06485199928283691

        …миллисекунд.
        Ответить
        • >while (Running_thread_counter < size - 1);
          какой багор) бизи вейт
          Ответить
        • > миллисекунд

          Мда. Выебать преждевременного оптимизатора наивным кодом на питоне - это бесценно.
          Ответить
          • Это не совсем питон, это всё таки компиляция питона нумбой
            Ответить
            • Да, чисто, к сожалению, не получится: на арифметических задачах «Питон» просто пиздец какой медленный.
              Ответить
              • Это потому, что у него все числа через указатели? Но они хотя бы int?
                JS со своим float тоже был бы медленный, когдаб не джит.
                Ответить
                • Потому что наивная интерпретация всего и бигинты.
                  >>> dis.dis(calc_unskill)
                    2           0 LOAD_GLOBAL              0 (range)
                                2 LOAD_CONST               1 (2)
                                4 LOAD_CONST               2 (1001)
                                6 CALL_FUNCTION            2
                                8 GET_ITER
                          >>   10 FOR_ITER                42 (to 54)
                               12 STORE_FAST               0 (x)
                  
                    3          14 LOAD_GLOBAL              0 (range)
                               16 LOAD_CONST               3 (1)
                               18 LOAD_CONST               4 (8500)
                               20 CALL_FUNCTION            2
                               22 GET_ITER
                          >>   24 FOR_ITER                26 (to 52)
                               26 STORE_FAST               1 (deg)
                  
                    4          28 LOAD_FAST                0 (x)
                               30 LOAD_FAST                1 (deg)
                               32 BINARY_POWER
                               34 LOAD_GLOBAL              1 (N)
                               36 COMPARE_OP               2 (==)
                               38 POP_JUMP_IF_FALSE       24
                  
                    5          40 LOAD_FAST                0 (x)
                               42 LOAD_FAST                1 (deg)
                               44 BUILD_TUPLE              2
                               46 YIELD_VALUE
                               48 POP_TOP
                               50 JUMP_ABSOLUTE           24
                          >>   52 JUMP_ABSOLUTE           10
                          >>   54 LOAD_CONST               0 (None)
                               56 RETURN_VALUE

                  Без «JIT» ВМ Питона просто берёт вот эти вот опкоды и тупо их исполняет до победного в одном внутреннем евале.

                  UPD: Только сейчас заметил: он же в самом горячем месте цикла делает LOAD_GLOBAL, то есть идёт в словарь и ищет в нём глобалку по имени. Какой анскилл )))
                  Ответить
                  • Да и BINARY_POWER - не самая быстрая операция. Нумба, видимо, заменила её на умножение.
                    Ответить
                • Ма-те-ма-ти-ки любят «Питон», потому что числа в нём переменного размера (bigint). Можно записать целое число с огромным количеством знаков и не думать о типах данных.
                  Ответить
                  • Я всегда был против строгой типизации. Поэтому я за PHP.
                    А явисты, <как> долбоёбы, ставят буковку "f" после дробных чисел )))
                    Ответить
  • Ебать там в комментариях самобытность!
    Barabashkad сегодня в 19:13
    для начала, CPU код можно еще оптимизиорвать если использовать векторные AVX инструкции
    но и для GPU… можно не мерять время выделения памяти и копирования…
    и тогда картина станет более многогранной и пестрой :-)

    И ни один петух не заметил, что для CPU-bound задачи цыплёнок запускает 1000 потоков…
    Ответить
    • >для CPU-bound задачи цыплёнок запускает 1000 потоков…
      это логично, если у тебя 1000 ядер
      Ответить
      • На видюхе их овер 3к. Так что он маловато тредов наделал.
        Ответить
        • какой смысл плодить треды на GPU, если ты cpu-баунд?
          Ответить
          • А где здесь cpu bound? Для брутфорса корня данных почти не надо передавать на видюху, число для проверки можно по индексам треда получить. В обратную сторону разве что мешок флажков придётся передать. И то я думаю можно reduce прям на видюхе сделать за несколько проходов.

            З.Ы. Я код не читал если что, там много буков.
            Ответить
    • А есть подробное условие задачи? Лень реверсить его по коду.
      Ответить
      • Для чисел от 0 до 999 (по одному на поток) и степеней от 1 до N (N задаётся в конкретном тесте) найти все пары (число, степень), которые при вычислении «число^степень» дают заданное в тесте число.
        Ответить
          • А, да, там unsigned.

            Показалось сначала, что по модулю UB. Какой багор )))
            Ответить
            • Ну тогда где здесь cpu bound, gost?

              Дождаться пока все треды на gpu закончат и пробежаться по массиву в 4 килобайта - не такая уж тяжёлая задача для cpu (на входе массив нинужен т.к. номер треда можно заюзать). Параллелится этот брутфорс вроде неплохо, память не напрягает (не то чтобы не было более красивого решения без брутфорса).
              Ответить
            • З.Ы. А, понял, ты про версию на cpu, где тыща обычных тредов поднимается. Ну да, выглядит пиздецово. С другой стороны в них IO нету, ось не будет контекст сильно часто переключать. Так что сойдёт. Вон даже gpu обогнать умудрились.
              Ответить
              • Да, про них.
                > ось не будет контекст сильно часто переключать
                Я недавно ради интереса одну CPU-bound задачку распараллелил на 4 потока (чтобы все ядра забить), померял, добавил ещё один и получил просадку в полтора раза. Добавил ещё то ли два, то ли три — просело во что-то вроде десяти раз. Так что не всё так однозначно (да и по заверениям автора, у него во время работы CPU-версии проц был загружен на 85%, лол).

                Ну и как бы вся задача — это несколько миллионов умножений, это считается реально за миллисекунды, если, конечно, считать, а не ебать планировщик.
                Ответить
                • Добавление потоков это всегда небольшой оверхед на их переключение, да и навреное они будут выталкивать из кеша данные друг друга?

                  А делать потоков больше, чем ядер, вообще смысла нету кмк: только шедулер зря грузить
                  Ответить
                  • > делать потоков больше, чем ядер, вообще смысла нету

                    На cpu нету. А вот на gpu есть. Там шедулер намного тоньше, другие треды смогут поработать пока первая группа ответ от памяти ждёт.
                    Ответить
                    • на ЦПУ такое же есть с внешними устройствами, заблокированный чтением тред вытесняется. Жаль, что нельзя так сделать с памятью.

                      Вообще, Задержки при обращении к памяти прозрачны для шедулера, потому профилировать их можно только с помощью специальных фич процессора
                      Ответить
                      • Ну аналог на cpu - это гипертрединг. Тоже позволяет паре тредов на одном ядре исполняться с очень тонким шедулингом.
                        Ответить
                        • Ну это делается прозрачно для шедулера всё равно: с его точки зрения это отдельные ядра, просто физически они делят какие-то куски цпу, и пока один питух что-то считает на ALU, другой может из памяти читать, вроде бы.

                          Хотя шедулер ведь может знать, что ядра на самом деле не настоящие, как-то это использовать.
                          Вообще же ГТ включает операционка. Некоторые операцинки его принципиально не включают из за безопастности)

                          OpenBSD has disabled Intel's hyper-threading technology, citing security concerns – seemingly, Spectre-style concerns. As detailed in this mailing list post, OpenBSD maintainer Mark Kettenis wrote that “SMT (Simultaneous Multi Threading) implementations typically share TLBs and L1 caches between threads

                          Если треды из разных процессов, то можно как-то сайд эффект атакой что-то спиздить...
                          Ответить
                          • > как-то это использовать

                            Вроде гипертреды стараются отдавать тредам одного процесса. Чтобы они могли "share TLBs and L1 caches" а не мешаться друг другу.
                            Ответить
                            • А вот вопрос: нужно ли защищать треды друг от друга?

                              На юниксах обычно треды имеют одинаковые (общие для процесса) права.

                              А на windows бывает имперсонация, когда тред получает дескриптор безопасности пользователя, так что в одном веб-сервере, на который зашли админ и гость, могут быть треды, работающие от имени гостя и админа. Если запустить их на одном ядре, то выполнение левого кода от имени гостя поможет хакеру угадать что лежит в "L1 caches" для админа, не?
                              Ответить
                              • Эм, ну ты же не даёшь гостю запускать его произвольный код в своём процессе под этой имперсонацией (это совсем ССЗБ, имхо, он же тебе в память насрёт без всякой спектры)? Ты просто для ядерного API выступаешь от его лица и всё. А код то твой в обоих тредах.
                                Ответить
                                • Да, но если гость хакер, то он сможет что-то поломать в моем коде, и запустить случайный код.

                                  nginx всегда работает от www, так что ssh ключи рута он не спиздит.
                                  А IIS (со включенной имперсонацией) может от имени доменного админа

                                  >ядерного API
                                  Токен можно использовать для обращения по сети (если клиент выдал такое разрешение)

                                  Веб сервер может пойти в базу данных от имени пользователя, например.
                                  Если у тебя AD, то это вообще довольно удобно.

                                  Хотя если хакер запустил случайный код от имени админа, то уже не важно, на каком ядре он выполняется
                                  Ответить
                                  • Кстати, давайте сравним модели безопасности у UNIX и Windows.

                                    У классического UNIX каждый процесс может иметь user id, причем user id можно заместить, так что есть real и effective user id.

                                    У файлов есть user id и group id и пермишены для них (я сейчас не говорю про ACL, это нашлёпка os-specific).

                                    Некоторые драйверы могут реально проверять user id пославшего им ioctl процесса, и слать нахуй, если это не root.

                                    У Windows каждый объект имеет ACL с указанием кому что можно, а каждый процесс (и даже тред) имеет 1 или более токенов безопасности.
                                    Такой токен имеет user sid и список привелегий (их миллион). Но такие токкены можно передавать другим процессам через IPС.

                                    Выдача токена называется logon session, и таких сессий может быть тоже миллион (на каждый вызов LogonAsUser), причем они все могут иметь разные привилегии и разные типы (interactive session, service итд)

                                    Какая модель лучше?
                                    Ответить
  • А вообще, "сравнения производительности" на хабре всегда чисто на поржать.
    Ответить
    • в комментах еще смешные нахрюки на кресты от тех, кто не знает крестов:

      "Про бойлерплейт с явным выделением и возвратом памяти я уже вообще молчу."
      Ответить
      • Кстати для cuda были контейнеры и аналоги крестовых алгоритмов которые на gpu крутятся.
        Ответить
        • Почему вообще не написали еще бекенд для llvm для GPU? Почему люди не могут писать на С++ для GPU? Или могут?
          Ответить
          • CUDA-конпелятор, который юзает чел из статьи, как раз таки позволяет в одном исходнике и для cpu и для gpu писать...

            Но у gpu очень специфичная архитектура и как попало под неё писать нельзя, иначе все терафлопсы вылетят в трубу. Сложный код, где много переменных, много нелокальных обращений к памяти, циклы переменной длины с внезапными бряками и т.п. видюхи очень плохо переносят. Им нужны тысячи и миллионы простых, независимых, однообразных задач.
            Ответить
            • Они охуеть какие спекулянты в вопросах выполнения кода и чтения из своей памяти?
              Ответить
              • > спекулянты

                Всё хуже. "Треды" исполняются группами по 16 штук, по сути это SIMD. Сам понимаешь, что control flow у них один на всех. Поэтому пока половина исполняет then, вторая пинает хуи. А потом наоборот. Ну и выйти из цикла они могут только всей группой.

                А у памяти большое латенси и маленькие кеши, что-то в духе сотни килобайт на "тыщу ядер" (один мультипроцессор). Поэтому рандомный доступ куда попало очень дорого обходится.

                Ну и регистры статически распределяются, поэтому чем больше переменных - тем меньше тредов ты сможешь загнать на однин мультипроцессор.
                Ответить
                • Там небось бывают и царские анроллы по этой причине?
                  Ответить
                  • Ага, настолько царские, что иногда не влезает. У меня на гитхабе есть множество жюлиа на шейдерах. На старых интеловских карточках тупо не конпелируется из-за огромного цикла с бряком.
                    Ответить
                    • не влезает в кеш команд или в "секцию кода" (не знаю как это называется в гпу)?
                      Ответить
                      • Х.з., я не знаю как там код заливается. Возможно у тех карточек вообще фиксированная область была под код. На нвидии даже while (1); норм работает.
                        Ответить
                        • пнятно..

                          у обычных PE и ELF вроде бы есть секция .text, которую загрузчик мапит в сегмент code, причем странички всегда чистые (потому что самомодифицирующийся код это чаще всего харам) и их можно выкинуть из памяти

                          интересно, как это работает гпу
                          Ответить
                          • > самомодифицирующийся код

                            С некогерентными L1 кешами видеокарт это вообще пиздецом попахивает...
                            Ответить
                            • а там меси/меса нет?ты можешь типа писнуть в код, и в итоге на разных ядрах будет разный код, если ты его явно не флашнешь?

                              какой багор ))
                              Ответить
                              • Видюшным задачам не особо нужна когерентность. У тебя на каждом "проходе" вход и выход алгоритма с разными буферами работают. Поэтому кешам на входе можно не париться о кешах на выходе. А после прохода можно и флашнуть, один хер кеши маленькие.
                                Ответить
  • Хочу в крестах возможность дефиницировать все поля объекта в теле конструктора. Почему я должен явно заполнять поля сразу после двоеточия инициализатором? Пусть бы они были неинициализированные пока (а не с дефолтными значнеиями), я бы просто обещал, что к концу конструктора я их чем-то заполню. Или так можно, и я просто мудак?
    Ну а если не заполню, так сам пидор, и сломал RAII

    class Foo final
    {
    	const int m_foo; //хочу const
    	Foo()
    	{
    		// Do all
    		m_foo = 12; 
    	}
    }
    Ответить
      • разве?

        я думал тут сайт, где сразу отвечают на любой вопрос про крестам, даже на очень глупый.

        Кстати, у меня были кейсы, когда мне отвечали про лоу-левел питушню на говнокоде моментально, а на SO бы ни в жизни не ответили
        Ответить
    • Хочешь конст - ебись с двоеточием. Без конста можно и просто в теле конструктора присвоить. Жаль конечно, что они как в джавке не сделали, конпелятор вполне мог бы проверить, что ты ровно 1 раз присваиваешь и соблюдаешь правильный порядок.

      З.Ы. Можно и int m_foo = 12; если кресты свежие. Но с const'ом это не имеет особого смысла, только память зря тратить. Зачем тебе поле в котором всегда одно и то же?
      Ответить
      • А без конст могу?
        >Можно и int m_foo = 12;
        нет, не хочу.

        Хочу m_foo = BlueMoon() ? 12 : 42;

        >Жаль конечно, что они как в джавке не сделали,
        в джавке поля все равно имеют дефолтные значения: int будет 0, поинтер будет null.
        Можно даже передать this кому-то в констуркторе и получить багра: см leak of this
        Ответить
        • Ага, но в теле конструктора это будет уже присваивание, а не конструирование как в инициализаторе. Не то чтобы это реально мешало, но помнить об этом стоит.
          Ответить
          • ну как не мешает? вызовется ДРУГОЙ конструктор же?
            а рантаайм не заполнит сначала деволтным значением?

            Я хочу заполнить объектом, который НЕ ПОДДЕРЖИВАЕТ копирование (оператор присваивания), потому что я автор этого класса, и не хочу поддерживать копирование
            Ответить
            • Для int'ов и прочего говна - нет. Там будет мусор пока что-нибудь не присвоишь.

              У объектов сработает дефолтный конструктор, а потом ты в них присвоишь новое значение. Реальная проблема только если дефолтный конструктор тяжёлый, с побочками или его вообще нет. Но такого на практике почти не бывает.
              Ответить
              • Я не хочу дефолтный конструктор, он может быть тяжелый, да.

                В общем понятно: проще сделать инициализатор через статическую функицю (или в анонимном неймспейсе) и потечь.

                Вообще заметил, что в крестах создавая класс всегда нужно ответить на два вопроса:
                * поддерживает ли он копирование/присваивание? Если да, то как?
                * поддерживает ли он move? Если да, то как?

                в других языках нет

                А еще создавая шаблон всегда нужно понимать когда и как он будет инстанциироваться.

                Короче, все время приходится думать
                Ответить
                • > приходится думать

                  Ну дык, это как машина с ручной коробкой. Не хочешь думать - юзай джаву.
                  Ответить
                  • просто происходит парадигм шифт, и даже потом пиша на питоне ты думаешь: "а когда этот объект удалится? а нету ли случайно на него лишних ссылок?" итд

                    Кресты меняют психику, и делают из тебя излишне подозрительного перца
                    Ответить
                    • > Кресты меняют психику

                      Это да. Я вот вижу, что в питоне какое-то поведение не описано в доке. И вообще не юзаю его. А питонисты говорят: "чувак, да просто запусти и посмотри что будет".
                      Ответить
                      • именно) я знаю, что если что-то работает у меня в джавке, то скорее всего и на другой ос оно будет работать так же. нет смысла искать параграф в JLS.
                        Исключение составляют разве что гонки при несинхронизированных потоках и атомарность некоторых операций

                        А в крестах нифига: если у тебя что-то работает, то оно может тупо сломаться при обновлении компилятора, если ты не знаешь какой параграф спеки это гарантирует

                        Причем джава и джаваскрипт и сишарп хотябы имеют спеку, а питон например -- нет. Как работает сипайтон -- так и правильно.
                        Ответить
            • > НЕ ПОДДЕРЖИВАЕТ копирование

              Оператор мувающего присваивания прикрути ему. По аналогии с мув конструктором.
              Ответить
              • ну да, я его имел ввиду: вызовется не конструктор а оператор присваивания
                Ответить
                • Какой vanished )))
                  У кого-то остались бэкапы всего того, что было насрано через guest8?
                  Ответить
                  • Загружаю. Ещё пока (послезавтра будет нельзя) можно скачать вчерашний дамп НГК, до ванишей.
                    Ответить

Добавить комментарий

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8