Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Скорость выполнения участка кода.  (Прочитано 30307 раз)
0 Пользователей и 1 Гость смотрят эту тему.
AlexLaw
Участник

Offline Offline

« : 07-10-2018 14:05 » 

Здравствуйте знатоки Делфи.
Хочется посоветоваться с вами вот по какому вопросу.
Для меня важна скорость выполнения программы и поэтому я хочу задать некоторые вопросы,
но чтобы не выглядеть попрашайкой буду предлагать свои варианты решения.
Моя цель путем обсуждения получить наиболее быстрый код.
1. Что лучше использовать для оценки скорости,
Профайлер или такты https://habr.com/post/75234/ или измерять время?
Ну и первый вопрос:
Подсчитать кол-во установленных бит в UInt64.
Мои варианты
1.Вариант
(click to show)
Код:
function CountBitsInt64_(const u:UInt64):Integer;//кол уст бит
var
i,j,k:Integer;
begin
k:=0;
             for i:=63 downto 0 do  begin
             j := (u shr i) and 1;
                       case j  of
                                1:begin
                                k:=k+1;
                                end;
                       end;
             end;
result:=k;
end;
2.Вариант
(click to show)
Код:
//Подсчет количества установленных бит в integer
 function CountBits(const Value: integer): integer;
asm
mov ECX,EAX
xor EAX,EAX
test ECX,ECX
jz @@ending
@@counting:
shr ECX,1
adc EAX,0
test ECX,ECX
jnz @@counting
@@ending:
end;
//Подсчет количества установленных бит в Int64
function CountBitsInt64(const integer64:UInt64):integer;
var
high_bit,low_bit:Longword;
i,j:integer;
begin
low_bit:=integer64;
high_bit:=integer64 shr 32;
i:=CountBits(low_bit);
j:=CountBits(high_bit);
result:=i+j;
end;

Для относительнойоценки  скорости пока использую такты
Код:
function RDTSC: UInt64;
asm
 rdtsc
end;

Так вот второй вариант немного быстрей.
Какие есть еще более быстрые варианты?
Записан
AlexLaw
Участник

Offline Offline

« Ответ #1 : 07-10-2018 14:39 » 

Сразу хочу поставить следующий вопрос.
Имеются два массива
  WPieceStart: array [0..5]  of  UInt64 =(1152921504606846976,576460752303423488,9295429630892703744,2594073385365405696,4755801206503243776,71776119061217280);// начальная позиция
  BPieceStart: array [0..5]  of  UInt64 = (16,8,129,36,66,65280);

Преобразовать их в (FEN строку)-нотацию Форсайта — Эдвардса

Мой вариант
(click to show)
Код:
function U64toFen_(WP,BP:array  of  UInt64;col:Integer):WideString;
var
i,ii,j,z,swth,k:Integer;
strF,strN,strK,FenString:string;
Figure:UInt64;
begin
result:='';
strF:='KQRBNPkqrbnp';
FenString:='';
Figure:=0;
ii:=64;
      for i := 0 to 5 do begin
        Figure:=Figure or WP[i] or BP[i];
      end;
        for i:=63 downto 0 do  begin // i-номер уст бита
            j := (Figure shr i) and 1;//j-флаг уст бита
                case j  of
                     1:begin
                       for z := 5 downto 0 do begin
                         if (MaskOneBit[i] and WP[z])>0 then begin swth:=z+1;break; end;
                         if (MaskOneBit[i] and BP[z])>0 then begin swth:=z+7;break; end;
                       end;//опред тип фигуры
                     k:=ii-i;
                     StrK:=IntToStr(k-1);
                     if k=1 then StrK:='';
                     strN:=copy(strF,swth,1) + StrK;
                     FenString:=strN+FenString;
                     ii:=i;
                     end;//1
                end;//case
        if (i mod 8)=0 then begin
                     k:=ii-i;
                     StrK:=IntToStr(k);
                     if k=0 then StrK:='';
                     if i>0 then begin
                       FenString:='/'+strK+FenString;
                     end else FenString:=strK+FenString;
                     ii:=ii-k;
        end;//if
        end;//for     
  case col of
     0:FenString:=FenString+' w';
     1:FenString:=FenString+' b';
  end;
result:=FenString;
end;
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 07-10-2018 17:46 » 

Подсчет: второй вариант быстрее. И быстрее уже не будет. Еще ест табличный метод, но он может дать очень разные результаты в разных условиях.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
AlexLaw
Участник

Offline Offline

« Ответ #3 : 07-10-2018 17:57 » 

Для чего это нужно мне?
Когда то я пробовал свои силы в программировании шахмат.
Потом забросил.
Сейчас вернулся к этому вопросу.
Посмотрел свой генератор ходов и понял насколько он медленный.
Когда то я хотел добавить в прогу черного бота - добавил.

* test1.zip (325.12 Кб - загружено 473 раз.)
* dll16092018.zip (840.07 Кб - загружено 463 раз.)
Записан
darkelf
Молодой специалист

no
Offline Offline

« Ответ #4 : 08-10-2018 06:48 » 

Для относительнойоценки  скорости пока использую такты
Код:
function RDTSC: UInt64;
asm
 rdtsc
end;

Так вот второй вариант немного быстрей.
Какие есть еще более быстрые варианты?
Имхо, rdtsc можно использовать так явно только на одноядерных процессорах. На многоядерных или в многопроцессорных конфигурациях можно получить проблемы. В данном случае лучше пользоваться API предоставляемые ОС, что будет более портабельно (на ARM-ах команды rdtsc, например, нет) и надёжно. Если в Вашем случае подразумевается Windows, то можно воспользоваться QueryPerformanceFrequency()/QueryPerformanceCounter(), если Linux, то clock_gettime(CLOCK_MONOTONIC, ...).
« Последнее редактирование: 08-10-2018 06:50 от darkelf » Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 08-10-2018 06:52 » 

Конечно, второй вариант быстрее, но с таким же успехом можно и все переписать на асме.

Это обосновано в режиме realtime, но не в условиях ИИ, если уж так свербит скорость, то нужно рассматривать параллельные вычисления.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 09-10-2018 06:02 » 

AlexLaw, не знаю, как в дельфи, но, например, в c++ 64 раза сдвинуть переменную и посчитать сумму младших битов каждого результата сдвига - это вообще никак не отразиться на скорости. Можно в цикле.
Можно (если прямо так уж критична скорость) без цикла - 64 повторных команды: сдвиг и подсчёт переносов (код попухлее чутка). С табличным способом это сделается за 16 переходов и 8 сложений, если сделать 8 свичей по 256 значений каждый (код ещё более пухлый, хотя кто на это смотрит сейчас).
« Последнее редактирование: 09-10-2018 06:04 от Алексей++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 09-10-2018 07:24 » 

Свичи — плохо, 100% вероятности промаха предсказания перехода. Это хуже, чем обращение к памяти в табличном способе.
64 повторных блока команд не быстрее цикла: удлинение кода — лишнее обращение к памяти.
Табличный способ будет быстрее цикла при условии предзагрузки таблицы в кеш.
« Последнее редактирование: 09-10-2018 07:30 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 09-10-2018 07:37 » 

RXL, если не поленюсь - проверю )
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 09-10-2018 07:56 » 

Если учесть, что вызов функции — два обращения к памяти, да и цикл тестирования добавится, то длинный код будет не отличим от цикла, да и табличный при повторных вызовах станет быстрее, если между вызовами не вытеснят из кеша.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 09-10-2018 08:06 » 

ну лично мне цикл тоже больше по душе. Компактненько

Добавлено через 19 минут и 11 секунд:
накидал пабысраму.

В дебаге, 20 миллионов итераций
цикл     - 7 секунд
64 шага  - 7 секунд
свичи    - 2 секунды


В релизе, 10 миллиардов итераций
цикл     - 10 секунд
64 шага  - 10 секунд
свичи    - 10 секунд


число, где считались биты, везде одно и то же == 0x123456789abcdef0

Время измерял ударами пальца об стол, точность плюс-минус секунда  Краснею

короче говоря, можно использовать цикл, так как в релизе разница незаметна
« Последнее редактирование: 09-10-2018 08:26 от Алексей++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #11 : 09-10-2018 08:35 » 

про релиз есть сомнения, мне кажется, там оптимизатор повыкидывал "лишние" пару-десяток миллиардов вызовов . Если убираю вызов функций в циклах, время выполнения такое же
Записан

darkelf
Молодой специалист

no
Offline Offline

« Ответ #12 : 09-10-2018 10:42 » 

Для подсчёта бит, если поддерживает процессор, можно воспользоваться командой popcnt. Для gcc/icc есть builtin-ы/instinsic-и.
Записан
AlexLaw
Участник

Offline Offline

« Ответ #13 : 13-10-2018 06:04 » 

Здравствуйте.
Может быть есть желающие для совместного создание быстрого генератора шахматных ходов на Делфи?
Визуализация доски представлена ниже.

Она имеет вид:
(MSB) 0010…010001 (LSB)
LSB – least significant bit младший бит - a8
MSB – most significant bit старший бит -h1

Для отображения всей шахматной позиции будем использовать набор из 12 BitBoard.
Фигуры представим двумя массивами:
WPiece-для белых,
BPiece-для черных, где индекс соответствует следуещему
0-KING-Король
1-QUEEN-Ферзи
2-ROOK-Ладьи
3-BISHOP-Слоны
4-KNIGHT-Кони
5-PAWN-Пешки

Давайте начнем с ладьи.



* BaseVisible13102018.zip (153.32 Кб - загружено 457 раз.)
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 13-10-2018 12:03 » 

А цель какая? Цель всегда первична.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
AlexLaw
Участник

Offline Offline

« Ответ #15 : 13-10-2018 12:50 » 

А цель какая? Цель всегда первична.
Недавно мне на глаза попалась вот такая прога https://zipproth.de/jetchess/index.html
Так вот меня поразила огромная скорость ее работы

Как видно из рисунка на глубину depth=8 она тратит всего 1,5 минуты.
Я не профессиональный программист, а любитель самоучка.
Поэтому и предложил всем миром попробовать хоть немного приблизиться к такому достижению.
К тому же у меня "замылилися" глаз.
Ну и может кому интересно поработать в команде.
как-то так.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 13-10-2018 13:47 » new

AlexLaw,

- что такое генератор шахматных ходов, что он должен делать ?

- насчёт скорости работы вообще - попробуй писать на c++ (на Qt, например, там с графикой попроще возюкаться, если что. И ассемблерные вставки не нужны будут

- почему для описания доски ты взял именно uint64 ? Как в одном бите сохранить всю информацию о фигуре ?

- почему нужно изобретать движок, когда их наверняка уже много. Разве что для тренировки навыков )
Записан

AlexLaw
Участник

Offline Offline

« Ответ #17 : 13-10-2018 14:09 » 

AlexLaw,
- что такое генератор шахматных ходов, что он должен делать ?
он должен генерировать все легальные ходы в соответствии с шахматными правилами.
это может быть список ходов или как у меня число IUnt64 - где каждый бит - это допустимый ход
AlexLaw,

- насчёт скорости работы вообще - попробуй писать на c++ (на Qt, например, там с графикой попроще возюкаться, если что. И ассемблерные вставки не нужны будут

с++ не знаю, не изучал.
С графикой нет проблем
Визуализация доски представлена ниже.
AlexLaw,
 Как в одном бите сохранить всю информацию о фигуре ?
Выше написал, как это выглядит
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 13-10-2018 14:59 » 

AlexLaw, то есть, результат работы такого генератора для одного конкретного расположения фигур - это тридцать два 64-битных значения ?

для каждого типа фигуры можно заранее сгенерировать (один раз в начале работы программы) маску его всех его ходов из каждой клетки (это массив uint64[64] для каждого типа фигур) . Тогда генерация его текущих ходов сводится к взятию нужной маски из этого массива и вычитанию позиций всех текущих фигур. Это будет работать очень быстро

кстати, используешь ли многопоточность? Данная задача легко распараллеливается
« Последнее редактирование: 13-10-2018 15:02 от Алексей++ » Записан

AlexLaw
Участник

Offline Offline

« Ответ #19 : 13-10-2018 15:10 » 

AlexLaw, то есть, результат работы такого генератора для одного конкретного расположения фигур - это тридцать два 64-битных значения ?
Да
AlexLaw,
кстати, используешь ли многопоточность? Данная задача легко распараллеливается
Нет
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #20 : 13-10-2018 15:11 » 

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

AlexLaw
Участник

Offline Offline

« Ответ #21 : 13-10-2018 16:57 » 

AlexLaw,
для каждого типа фигуры можно заранее сгенерировать (один раз в начале работы программы) маску его всех его ходов из каждой клетки (это массив uint64[64] для каждого типа фигур) . Тогда генерация его текущих ходов сводится к взятию нужной маски из этого массива и вычитанию позиций всех текущих фигур.
Пока не вижу, как это может работать.

Например в начальной позиции у ферзя на d1 нет ходов, а после пешкой e2-e4, появляется ход по диагонали e2-h5.

Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #22 : 13-10-2018 17:11 » 

AlexLaw, да, я не учёл загораживание пути. Это тоже дополнительная обработка - проверЯть преграды на путях. Тем не менее, вычитание маски всё равно будет отсеивать очень много мусора. Опять же, для каждой маски можно (при её генерации) сохранить путь в приращениях, чтобы не генерировать каждый раз этот путь при проверке препятствий (это я уже в преждевременную оптимизацию ударился)

Другой путь - хранить не 64 бита, а 64 байта (к ним адресоваться проще в плане скорости, ну и 7 дополнительных битов можно использовать для чего-нибудь), тогда от фигур можно будет шагать во всех направлениях по нужным правилам, прерываясь, если там есть фигура или удар (для короля)

я вот так с ходу даже и не могу сказать, какой путь будет быстрее. Разве что всё это попробовать реализовать и сравнить
« Последнее редактирование: 13-10-2018 17:15 от Алексей++ » Записан

AlexLaw
Участник

Offline Offline

« Ответ #23 : 20-10-2018 19:53 » 

Решил попробовать использовать маски для нахождения ходов.
Пока в голове созрела концепция, но что получится не знаю.
Пока только атаки  для ладьи.
PS
Пропустил через профайлер

PS
Атаки для всех фигур ниже


Добавлено через 12 дней, 14 часов, 49 минут и 42 секунды:
Кстате, кто хочет порешать шахматные задачки.
Boт еще несколько.
(click to show)
8/8/4K3/2B5/3N4/4k3/2Q5/8 мат 2 хода
k2r4/2R2p2/1RKPP3/1BP5/8/1pqp4/8/7Q мат 2 хода
8/8/8/8/K5QB/3pR3/4N1n1/3k4 мат 2 хода
3n2q1/3p1rbb/KR6/3Q1Br1/3NN3/n1pk4/5B2/8 мат 2 хода
q1k1b3/pNPN1p2/5Pp1/6K1/8/8/2R5/7Q мат 2 хода
3R4/4K2p/b4p2/p3p1n1/QBk3B1/R7/8/b3r3 мат 2 хода
B2R1B2/2P3p1/1pPr4/pP4PK/p2kP3/P5Q1/Pn3N2/1R6 мат 3 хода
7Q/2NP2rq/1pKBRr2/1P3P1n/2Nkp3/1P6/5n1b/1BR5 мат 2 хода
8/8/Q6p/4pRp1/3p4/3Nk2p/8/2K2b2 мат 3 хода
5B2/2p1N3/3PPk2/3P4/5K2/2P5/8/8 мат 4 хода
7k/6qp/7p/3B3p/3R4/8/1BK1P3/8 мат 3 хода
8/8/8/4ppP1/4NR1B/8/2K1ppp1/4bbrk мат 3 хода
4n3/3NNQ2/1p6/1P1pPp2/2PrkrP1/2Rp1pR1/3PP3/K7 мат 2 хода
Вставить в файл fen.txt из поста
Когда то я пробовал свои силы в программировании шахмат.

Добавлено через 14 дней, 2 часа, 28 минут и 23 секунды:

пробный вариант

Добавлено через 9 дней, 21 час, 3 минуты и 24 секунды:
Добавлена связка, но нужно тестировать.
Осталось взятие на проходе.

Добавлено через 7 дней, 23 часа, 38 минут и 3 секунды:
Для тех кто любит мастерить своими руками предлагаю повторить конструкцию
шахматных часов на Arduino

(click to show)
(click to show)
(click to show)
https://youtu.be/Z8XlJFgqbMI
(click to show)
Код:
const int clock1 = 7;
const int data1 = 8;
const int clock2 = 5;
const int data2 = 6;
const int red = 9;
const int selector = 11;
boolean swith=true;
const int yellow = 10;
byte dot = 128;
byte m1 = 5;
byte m2 = 5;
byte s1 = 0;
byte s2 = 0;
boolean x;
                  /*0*/ /*1*/ /*2*/ /*3*/ /*4*/ /*5*/ /*6*/ /*7*/ /*8*/ /*9*/
uint8_t digits2[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };
uint8_t digits1[] = { 0x3f, 0x30, 0x5b, 0x79, 0x74, 0x6d, 0x6F, 0x38, 0x7f, 0x7D };
const int pinread=2;
const int btnPin = 3;
unsigned long t;
unsigned long t1;
unsigned long t2;
void setup() {
pinMode(selector, INPUT_PULLUP); 
pinMode(btnPin, INPUT_PULLUP);
pinMode(red, OUTPUT);
pinMode(yellow, OUTPUT);
digitalWrite(red, LOW);
digitalWrite(yellow, HIGH);
attachInterrupt(1, Stop, FALLING);
setupInterrupt(); 
pinMode(clock1, OUTPUT);
pinMode(data1, OUTPUT);
pinMode(clock2, OUTPUT);
pinMode(data2, OUTPUT);
pinMode(pinread, OUTPUT);
t1=0;
t2=0;
start(clock1,data1);
writeValue(clock1,data1,0x8c);
stop(clock1,data1);
start(clock2,data2);
writeValue(clock2,data2,0x8c);
stop(clock2,data2);
// clear display
write(clock1,data1,0x00, 0x00, 0x00, 0x00);
write(clock2,data2,0x00, 0x00, 0x00, 0x00);
//write(clock1,data1,digits1[1], digits1[2] | dot, digits1[3], digits1[4]);
// write(clock2,data2,digits2[8], digits2[7] | dot, digits2[6], digits2[5]);
swith = digitalRead(selector);
pinMode(selector, INPUT);
}
byte tcnt2;
unsigned long time = 0; // 86390000;
void Stop () {
/* First disable the timer overflow interrupt*/
TIMSK2 &= ~(1<<TOIE2);
digitalWrite(yellow, LOW);
digitalWrite(red, HIGH); 
}

void loop() {
x = digitalRead(pinread);
if (swith){
reverseTime();
} else {
forwardTime();
}
}
void forwardTime(){
t = (unsigned long)(time/1000);
if (x) {
t1=t-t2;   
} else {
t2=t-t1;
}
uint8_t minutes1 = (byte)((t1 / 60) % 60);
uint8_t seconds1 = (byte)(t1 % 60);
uint8_t minutes2 = (byte)((t2 / 60) % 60);
uint8_t seconds2 = (byte)(t2 % 60);   
write(clock1,data1,digits1[seconds2 % 10],digits1[seconds2 / 10] | ((seconds2 & 0x01) << 7),digits1[minutes2 % 10],digits1[minutes2 / 10]);
write(clock2,data2,digits2[minutes1 / 10], digits2[minutes1 % 10] | ((seconds1 & 0x01) << 7) , digits2[seconds1 / 10], digits2[seconds1 % 10]); 
}
void reverseTime() {
t = (unsigned long)(time/100);
if (x) {
t1=t-t2;
m1=4;
s1=59;   
} else {
t2=t-t1;
m2=4;
s2=59;
}
uint8_t minutes1 = m1-(byte)((t1 / 600) % 60);
uint8_t seconds1 = s1-(byte)((t1 / 10) % 60);
uint8_t minutes2 = m2-(byte)((t2 / 600) % 60);
uint8_t seconds2 = s2-(byte)((t2 / 10) % 60);
uint8_t ms2 = 9 -(byte)(t2 % 10);
uint8_t ms1 = 9 -(byte)(t1 % 10);
if (t2<3000){
 if (t2>2400) {
 write(clock1,data1,0,digits1[ms2] | dot,digits1[seconds2 % 10],digits1[seconds2 / 10]);     
 } else {
 write(clock1,data1,digits1[seconds2 % 10],digits1[seconds2 / 10] | dot,digits1[minutes2 % 10],digits1[minutes2 / 10]); 
 }
}
if (t1<3000){
  if (t1>2400) {
write(clock2,data2,digits2[seconds1 / 10], digits2[seconds1 % 10] | dot, digits2[ms1], 0);   
  } else {
write(clock2,data2,digits2[minutes1 / 10], digits2[minutes1 % 10] | dot, digits2[seconds1 / 10], digits2[seconds1 % 10]);   
  }
}
}
void setupInterrupt()
{
/* First disable the timer overflow interrupt while we're configuring */
TIMSK2 &= ~(1<<TOIE2);

/* Configure timer2 in normal mode (pure counting, no PWM etc.) */
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);

/* Select clock source: internal I/O clock */
ASSR &= ~(1<<AS2);

/* Disable Compare Match A interrupt enable (only want overflow) */
TIMSK2 &= ~(1<<OCIE2A);

/* Now configure the prescaler to CPU clock divided by 128 */
TCCR2B |= (1<<CS22)  | (1<<CS20); // Set bits
TCCR2B &= ~(1<<CS21);             // Clear bit

/* We need to calculate a proper value to load the timer counter.
* The following loads the value 131 into the Timer 2 counter register
* The math behind this is:
* (CPU frequency) / (prescaler value) = 125000 Hz = 8us.
* (desired period) / 8us = 125.
* MAX(uint8) + 1 - 125 = 131;
*/
/* Save value globally for later reload in ISR */
tcnt2 = 131;

/* Finally load end enable the timer */
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);
}

/*
* Install the Interrupt Service Routine (ISR) for Timer2 overflow.
* This is normally done by writing the address of the ISR in the
* interrupt vector table but conveniently done by using ISR()  */
ISR(TIMER2_OVF_vect) {
/* Reload the timer */
TCNT2 = tcnt2;

time++;
time = time % 86400000;
}
void write(int clock,int data,uint8_t first, uint8_t second, uint8_t third, uint8_t fourth)
{
start(clock,data);
writeValue(clock,data,0x40);
stop(clock,data);

start(clock,data);
writeValue(clock,data,0xc0);
writeValue(clock,data,first);
writeValue(clock,data,second);
writeValue(clock,data,third);
writeValue(clock,data,fourth);
stop(clock,data);
}
void start(int clock,int data)
{
digitalWrite(clock,HIGH);//send start signal to TM1637
digitalWrite(data,HIGH);
delayMicroseconds(5);

digitalWrite(data,LOW);
digitalWrite(clock,LOW);
delayMicroseconds(5);
}

void stop(int clock,int data)
{
digitalWrite(clock,LOW);
digitalWrite(data,LOW);
delayMicroseconds(5);

digitalWrite(clock,HIGH);
digitalWrite(data,HIGH);
delayMicroseconds(5);
}
bool writeValue(int clock,int data,uint8_t value)
{
for(uint8_t i = 0; i < 8; i++)
{
 digitalWrite(clock, LOW);
 delayMicroseconds(5);
 digitalWrite(data, (value & (1 << i)) >> i);
 delayMicroseconds(5);
 digitalWrite(clock, HIGH);
 delayMicroseconds(5);
}

// wait for ACK
digitalWrite(clock,LOW);
delayMicroseconds(5);

pinMode(data,INPUT);

digitalWrite(clock,HIGH);
delayMicroseconds(5);

bool ack = digitalRead(data) == 0;

pinMode(data,OUTPUT);

return ack;
}



Добавлено через 7 дней, 10 часов, 26 минут и 37 секунд:
Взятие на проходе.
Файлы проекта и скомпилированный файл.
Не совсем удовлетворен решением со "Взятие на проходе"
Теперь нужно писать функцию Perft-https://www.chessprogramming.org/Perft_Results
для проверки
Unit2-немного причесал

Добавлено через 6 дней, 6 часов, 6 минут и 40 секунд:
Bсе ходы для фигур одного цвета.
Я думаю нужно код оптимизировать, но нужно время.
И скомпилированный файл.

* MoveGenerator20102018.zip (487.48 Кб - загружено 438 раз.)
* Unit2.zip (7.42 Кб - загружено 472 раз.)
* 25102018Unit2.zip (8.64 Кб - загружено 435 раз.)
* 26102018Unit2.zip (9.09 Кб - загружено 449 раз.)
* Безымянный 1.png (254.39 Кб - загружено 449 раз.)
* MoveGenerator28102018.zip (246.01 Кб - загружено 445 раз.)
* MoveGenerator.zip (305.4 Кб - загружено 450 раз.)
* 28102018Unit2.zip (10.2 Кб - загружено 446 раз.)
* 03102018MoveGenerator.zip (225.43 Кб - загружено 435 раз.)
* MoveGenerator.zip (305.9 Кб - загружено 417 раз.)
« Последнее редактирование: 03-11-2018 22:44 от AlexLaw » Записан
AlexLaw
Участник

Offline Offline

« Ответ #24 : 05-11-2018 17:38 » 

Набросал функцию проверки.
Поразительно, но даже близко по скорости не подобрался.

39 миллисекунд у товарища

20 мин у меня
К тому же не совпадает кол-во ходов.
Пока без оптимизации.
« Последнее редактирование: 06-11-2018 21:54 от AlexLaw » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #25 : 06-11-2018 04:58 » 

AlexLaw, за 20 минут я вручную такой список составлю, что-то у тебя не так в подходе  Здесь была моя ладья...

дело даже не в языке. Я уверен, что даже на самом сраном бейсике минута - это максимум для такого перебора ходов ))

дельфи не знаю, проверить не смогу. Может, где-то что-то объёмное не по ссылке, а по значению передаёшь там, где достаточно ссылку.
Записан

AlexLaw
Участник

Offline Offline

« Ответ #26 : 10-11-2018 10:33 » 

Исправил некоторые ошибки, но не все.
Буду признателен, если кто-нибудь укажет не корректный ход.
Для этого прогу сделал с уклоном на отладку.
Сравнивать с эталонной супер прогой https://zipproth.de/jetchess/index.html
или https://www.chessprogramming.org/Perft_Results
Скорее всего взятие на проходе.


Добавлено через 13 часов, 39 минут и 53 секунды:
Я так понял, что тут на форуме много знающих C и C++.
Может быть совместно разберем алгоритм написанный на Си и реализуем его на Делфи.
Нашел на одном из форумов код на Си.
Скомпилировал, вот что получилось

Как видно работает быстро.
Может совместно  разберем алгоритм и напишем на Делфи.
Или соберем dll.
PS
в крайнем случае, если мне будет чтото непонятно помочь советом


* Perft10112018.zip (218.91 Кб - загружено 409 раз.)
* Perft.zip (322.57 Кб - загружено 426 раз.)
* main.zip (10.28 Кб - загружено 399 раз.)
« Последнее редактирование: 11-11-2018 13:52 от AlexLaw » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #27 : 11-11-2018 15:36 » 

Не совсем понятно, что нужно разбирать, если он уже написан (и даже работает!)?

если мне будет чтото непонятно помочь советом
а вот это всегда пожалуйста.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
AlexLaw
Участник

Offline Offline

« Ответ #28 : 11-11-2018 15:45 » 

Не совсем понятно, что нужно разбирать, если он уже написан (и даже работает!)?
Я имел ввиду переписать этот код на Делфи или создать dll на его основе.
Использовать такой же подход (алгоритм)
« Последнее редактирование: 11-11-2018 15:47 от AlexLaw » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #29 : 11-11-2018 15:47 » 

AlexLaw, алгоритм - это не язык программирования, это последовательность действий

например
Код:
//N-номер хода. Глубина - 10 ходов

//"доска" - содержит текущую ситуацию на доске (и ход, приведший к рождению доски)
//"(стек N)" - содержит стартовые доски N-го хода
//"<<" - операция добавления доски в стек
int N=0
инициализируем (стек N)<<(доска) // только что расставили фигуры

for(N=N+1; N<=10; N++)
{
if( (стек N-1) существует )
{
вытаскиваем из (стека N-1) очередную доску Д1

for(шагаем по всем фигурам доски Д1)
{
for(перебираем возможные шаги текущей фигуры Ф1 доски Д1)
{
доска Д2 = Д1 + (шаг фигуры Ф1 со всеми результатами шага)
(стек N)<<Д2
}
}
}
}

результат работы - список стеков 0,1,...,10
« Последнее редактирование: 11-11-2018 15:49 от Алексей++ » Записан

Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines