- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 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; }
}
}
}
P. S. Перевёл алгоритм автора на «Python» с «Numba», третий с конца результат, который у него считался 16 секунд, вычислил за 65.
…миллисекунд.
Мда. Выебать преждевременного оптимизатора наивным кодом на питоне - это бесценно.
Без «JIT» ВМ Питона просто берёт вот эти вот опкоды и тупо их исполняет до победного в одном внутреннем евале.
UPD: Только сейчас заметил: он же в самом горячем месте цикла делает LOAD_GLOBAL, то есть идёт в словарь и ищет в нём глобалку по имени. Какой анскилл )))
А явисты, <как> долбоёбы, ставят буковку "f" после дробных чисел )))
И ни один петух не заметил, что для CPU-bound задачи цыплёнок запускает 1000 потоков…
З.Ы. Я код не читал если что, там много буков.
По модулю 2**64?
Показалось сначала, что по модулю UB. Какой багор )))
Дождаться пока все треды на gpu закончат и пробежаться по массиву в 4 килобайта - не такая уж тяжёлая задача для cpu (на входе массив нинужен т.к. номер треда можно заюзать). Параллелится этот брутфорс вроде неплохо, память не напрягает (не то чтобы не было более красивого решения без брутфорса).
> ось не будет контекст сильно часто переключать
Я недавно ради интереса одну CPU-bound задачку распараллелил на 4 потока (чтобы все ядра забить), померял, добавил ещё один и получил просадку в полтора раза. Добавил ещё то ли два, то ли три — просело во что-то вроде десяти раз. Так что не всё так однозначно (да и по заверениям автора, у него во время работы CPU-версии проц был загружен на 85%, лол).
Ну и как бы вся задача — это несколько миллионов умножений, это считается реально за миллисекунды, если, конечно, считать, а не ебать планировщик.
На cpu нету. А вот на gpu есть. Там шедулер намного тоньше, другие треды смогут поработать пока первая группа ответ от памяти ждёт.
Вроде гипертреды стараются отдавать тредам одного процесса. Чтобы они могли "share TLBs and L1 caches" а не мешаться друг другу.
Но у gpu очень специфичная архитектура и как попало под неё писать нельзя, иначе все терафлопсы вылетят в трубу. Сложный код, где много переменных, много нелокальных обращений к памяти, циклы переменной длины с внезапными бряками и т.п. видюхи очень плохо переносят. Им нужны тысячи и миллионы простых, независимых, однообразных задач.
Всё хуже. "Треды" исполняются группами по 16 штук, по сути это SIMD. Сам понимаешь, что control flow у них один на всех. Поэтому пока половина исполняет then, вторая пинает хуи. А потом наоборот. Ну и выйти из цикла они могут только всей группой.
А у памяти большое латенси и маленькие кеши, что-то в духе сотни килобайт на "тыщу ядер" (один мультипроцессор). Поэтому рандомный доступ куда попало очень дорого обходится.
Ну и регистры статически распределяются, поэтому чем больше переменных - тем меньше тредов ты сможешь загнать на однин мультипроцессор.
С некогерентными L1 кешами видеокарт это вообще пиздецом попахивает...
З.Ы. Можно и int m_foo = 12; если кресты свежие. Но с const'ом это не имеет особого смысла, только память зря тратить. Зачем тебе поле в котором всегда одно и то же?
У объектов сработает дефолтный конструктор, а потом ты в них присвоишь новое значение. Реальная проблема только если дефолтный конструктор тяжёлый, с побочками или его вообще нет. Но такого на практике почти не бывает.
Ну дык, это как машина с ручной коробкой. Не хочешь думать - юзай джаву.
Это да. Я вот вижу, что в питоне какое-то поведение не описано в доке. И вообще не юзаю его. А питонисты говорят: "чувак, да просто запусти и посмотри что будет".
Оператор мувающего присваивания прикрути ему. По аналогии с мув конструктором.
У кого-то остались бэкапы всего того, что было насрано через guest8?