Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.64/25: Рейтинг темы: голосов - 25, средняя оценка - 4.64
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676

Варианты конвертации bool/byte/int в byte/int

11.01.2019, 12:56. Показов 5864. Ответов 102
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В Си, если мне не изменяет память можно наоборот любые данные интерпретировать как true/false. А вот меня интересует преобразование числовых данных отличных от нуля в единицу, а нулевых значений в ноль.
Я воспользовался уже двумя реализациями (на самом деле есть еще две, но они сильно зависят от контекста и не являются универсальными), и по производительности остановился на первой:
1)
C#
1
2
3
byte x1;
byte x2;
x2 = (byte)((x1) == 0 ? 0 : 1);
2) у меня данные не могут быть более 32, поэтому такой вариант тоже возможен
C#
1
2
3
4
public static readonly byte[] BitsValue =    { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
byte x1;
byte x2;
x2 = BitsValue[x1];
Если написал сумбурно, то меня интересует код, который из любого положительного числа делает 1, а из нуля - 0. Так же как частный случай использовался такой код:
C#
1
2
3
byte x1;
byte x2;
x2 = (byte)((x1 & 8) >> 3);
Что можете подсказать ещё?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.01.2019, 12:56
Ответы с готовыми решениями:

int в byte
как перевести int в byte а потом обратно в int???

Как переконвертировать int в byte[]?
Как переконвертировать hex занчение int в byte? Чтобы int a = 0x45C5; cтало byte b = new byte {0x45, 0xC5}; udp: и наоборот тоже

Ошибка после конвертации метода на С++ к С#: "Неявное преобразование типа "int" в "bool" невозможно"
Ошибка после преобразования метода на С++ к С#: "Неявное преобразование типа "int" в "bool" невозможно" Метод взят...

102
95 / 74 / 27
Регистрация: 13.08.2018
Сообщений: 203
18.01.2019, 03:56
Студворк — интернет-сервис помощи студентам
Чуть ускорил, теперь считает за три секунды.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
 
namespace CalcBitsCL
{
    class Program
    {
        static object locker = new object();
 
        // это расчётные значения для работы с матрицей 5х5, но с фиксированным одним значение верхнего элемента, я тестировал со значением 0, но работает и с любым но одиночным значением
        // это большая оптимизация которая позволила резко сократить число операций, значения в массиве обозначают места для разных значений SumBits
        // идея в том, что сравнивать одни данные с другими имеет смысла только если суммы бит одинаковые, так мы сокращаем число итераций для For(Compare)
        public static readonly int[] DimIdx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
        public static int[] countNidx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
 
        public static DimBitsS[] DimBitsSN = new DimBitsS[1048576]; // число элементов матрицы 5х5, но для одного значения верхнего вектора, то есть формально 2 в двадцатой степени + 1
        public static byte SumBits = 0; // хранит сумму бит, является так же индексом для DimIdx и countNidx
 
        public static byte x1, x2, x3, x4, x5; // числа, используемые для отражения значений матрицы 5х5, x1 - верх, x5 - низ
 
        public static ulong countN = 0; public static ulong countIn = 0; public static ulong countX, old_countX; public static int num1, num2;
 
        public class DimBitsS
        {
            public byte[] Bits; // массив сумм бит
            public int Sum; // значение SumBits сохранённое во время расчета каждого элемента
            public byte Hash; // XOR хэш
            public byte CRC8; // CRC8
            public int zip;
            public DimBitsS(int _Sum) // инициализация
            {
                this.Sum = _Sum;
                this.Hash = 0;
                this.CRC8 = 0;
                this.Bits = new byte[28];
                zip = 0;
            }
        }      
 
        public static byte BitCount(ulong value) // считаем число бит в переменной
        {
            ulong result = value - ((value >> 1) & 0x5555555555555555UL);
            result = (result & 0x3333333333333333UL) + ((result >> 2) & 0x3333333333333333UL);
            return (byte)(unchecked(((result + (result >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56);
        }
 
        class C
        {
            public int Begin, End, Zip;
            public C(int begin, int end, int zip)
            {
                Begin = begin;
                End = end;
                Zip = zip;
            }           
 
            public override string ToString()
            {
                return $"{Begin} : {End} : {Zip}";
            }
        }
 
        static void Main(string[] args)
        {
            int counter = 0;
 
            var ranges = new List<C>();
 
            int temp, old_percent = 0; // инициализация счетчиков и временных переменных
            num1 = 0; num2 = 0;
            if (num1 >= num2) num2 = num1 + 1; else num2++; // по большому счёту нужно только если первое и второе значения менять, если ничего не трогать, то можно не обращать внимание
            for (x1 = (byte)num1; x1 < (byte)num2; x1++) // первая переменная из матрицы 5х5 бит (условно верхняя)
            {
                countN = 0; countX = 0; old_countX = 0; // инициализация счетчиков
                var sw = Stopwatch.StartNew(); // запуск таймера
                for (x2 = 0; x2 < 32; x2++) // вторая переменная из матрицы
                {
                    // обновление элементов на форме, происходит только если данные изменились
                    temp = (int)((ulong)countN * (ulong)(x1 + 1) * 100 / (ulong)(Math.Pow(32, 4) * (num2 - num1))); // тут я набредил и больше не трогал, используется для вычисления шкалы ProgressBar, нормально работает для одного значения x1, по если x1 > 0 будет показывать криво
                                                                                                                    // обновление ProgressBar и Label с процентом
                                                                                                                    // порой достаточно посмотреть 50% от всей программы (это примерно 33% от всего объёма вычислений)
                    if (old_percent != temp)
                    {
                        Console.WriteLine(temp.ToString() + "%");
                        old_percent = temp;
 
                    }
 
                    //if (counter++ > 3)
                    //{
                    //    goto exit;
                    //}
 
                    for (x3 = 0; x3 < 32; x3++) // третья переменная из матрицы
                    {
                        for (x4 = 0; x4 < 32; x4++) // четвертая из матрицы
                        {
                            for (x5 = 0; x5 < 32; x5++) // пятая переменная
                            {
                                SumBits = (byte)(BitCount(x1) + BitCount(x2) + BitCount(x3) + BitCount(x4) + BitCount(x5)); // сумма сумм бит
 
                                DimBitsSN[countNidx[SumBits]] = new DimBitsS(SumBits); // инициализация данных в структуре                             
 
 
                                DimBitsSN[countNidx[SumBits]].zip = BitCount(x1) | BitCount(x2) << 3 | BitCount(x3) << 6 | BitCount(x4) << 9 | BitCount(x5) << 12;                               
 
                                // запускаем основной цикл сравнения. Условие смотрит только за тем, чтобы проверка запускалась только если более одного значения посчитано
                                if (countN > 0 && DimIdx[SumBits] != countNidx[SumBits])
                                {
                                    ranges.Add(new C(
                                        DimIdx[SumBits],
                                        (DimIdx[SumBits] == countNidx[SumBits] ? countNidx[SumBits] + 1 : countNidx[SumBits]),
                                        DimBitsSN[countNidx[SumBits]].zip)
                                        );
                                }
 
                                countN++; // общее число итераций
                                countNidx[SumBits]++; // движение указателей на данные
                            }
                        }
                    }
                }                
            }
 
            exit:           
 
            foreach (var group in ranges.OrderBy(x => x.Begin).GroupBy(x => x.Begin))
            {
                int i = group.Key;
 
                ulong[] data = new ulong[1 << 16];
 
                foreach (var item in group.OrderBy(x => x.End))
                {
                    for (; i < item.End; i++)
                    {
                        data[DimBitsSN[i].zip]++;
                    }
                    countIn += data[item.Zip];
                }
            }
 
            Console.WriteLine(countIn);
 
            Console.WriteLine("Цимес!!! Прес эни кий ту континью...");
            Console.ReadKey();
        }
    }
}
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
18.01.2019, 05:31  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
у меня ваш алгоритм с консольного проекта получилось ускорить примерно в 4.6 раза.
был бы рад увидеть изменения.

Цитата Сообщение от maximka777 Посмотреть сообщение
Чуть ускорил, теперь считает за три секунды.
моё
2260798720 : 50585009280 : 00:07:33.2875009

ваше
2015854720 : 00:00:00.5064325
значения выходные не совпадают.

я правильно понимаю что вы упаковываете матрицу в одну переменную int? этого делать не то чтобы не нужно - это не имеет смысла, так как 5 бит - частный случай и при 64 битах упаковывать будет некуда.
вы исключили сравнение "каждый с каждым", foreach (var group in ranges.OrderBy(x => x.Begin).GroupBy(x => x.Begin)) является его заменой?
0
95 / 74 / 27
Регистрация: 13.08.2018
Сообщений: 203
18.01.2019, 05:51
Цитата Сообщение от belalugoci Посмотреть сообщение
значения выходные не совпадают.
Это потому что хэш размером в байт слишком мало, поэтому считает не правильно.
Цитата Сообщение от belalugoci Посмотреть сообщение
при 64 битах упаковывать будет некуда.
Значит нужно считать хэш.
Цитата Сообщение от belalugoci Посмотреть сообщение
вы исключили сравнение "каждый с каждым"
А смысл ? Если хэши совпадают значит все равно будет.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,576
18.01.2019, 05:55
Цитата Сообщение от belalugoci Посмотреть сообщение
был бы рад увидеть изменения.
К сожалению не самая быстрая версия, эта у меня работает примерно 2:30 минуты, а самая быстрая была 2:15, но что в ней было я уже вряд ли смогу вспомнить... Пробовал очень много разных вариантов...

C#
1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
using System;
using static System.Threading.Tasks.Parallel;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
//using System.Runtime.CompilerServices;
 
namespace CalcBitsCL
{
    class Program
    {
        static object lockObj = new object();
 
        // это расчётные значения для работы с матрицей 5х5, но с фиксированным одним значение верхнего элемента, я тестировал со значением 0, но работает и с любым но одиночным значением
        // это большая оптимизация которая позволила резко сократить число операций, значения в массиве обозначают места для разных значений SumBits
        // идея в том, что сравнивать одни данные с другими имеет смысла только если суммы бит одинаковые, так мы сокращаем число итераций для For(Compare)
        public static readonly int[] DimIdx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
        public static int[] countNidx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
 
        public static DimBitsS[] DimBitsSN = new DimBitsS[1048576]; // число элементов матрицы 5х5, но для одного значения верхнего вектора, то есть формально 2 в двадцатой степени + 1
        //public static byte SumBits = 0; // хранит сумму бит, является так же индексом для DimIdx и countNidx
 
        //public static byte x1, x2, x3, x4, x5; // числа, используемые для отражения значений матрицы 5х5, x1 - верх, x5 - низ
 
        //public static ulong countN = 0;
        //public static ulong countIn = 0;
        //public static ulong countX, old_countX;
        //public static int num1, num2;
 
        public unsafe struct DimBitsS
        {
            //public byte[] Bits; // массив сумм бит
            public fixed byte Bits[28];
            public int Sum; // значение SumBits сохранённое во время расчета каждого элемента
            public byte Hash; // XOR хэш
            public byte CRC8; // CRC8
 
            //public DimBitsS(int _Sum, byte[] bits) // инициализация
            public DimBitsS(int _Sum) // инициализация
            {
                this.Sum = _Sum;
                this.Hash = 0;
                this.CRC8 = 0;
                //Bits = bits;
            }
        }
 
        public static void Compare(int y)
        {
        }
 
        public static byte BitCount64(ulong value) // считаем число бит в переменной
        {
            ulong result = value - ((value >> 1) & 0x5555555555555555UL);
            result = (result & 0x3333333333333333UL) + ((result >> 2) & 0x3333333333333333UL);
            return (byte)(unchecked(((result + (result >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56);
        }
 
        //static byte NumberOfSetBitsInt32(int i)
        //{
        //    i = i - ((i >> 1) & 0x55555555);
        //    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
        //    return (byte)(unchecked(((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
        //}
 
        static class CRC8 // расчет CRC8, нужно такое же, но на CRC32
        {
            static byte[] CRC8_TABLE = new byte[]{
                0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
                157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
                35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
                190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
                70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
                219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
                101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
                248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
                140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
                17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
                175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
                50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
                202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
                87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
                233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
                116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 };
 
            public static unsafe byte Calculate(byte* data, byte init = 0)
            {
                byte result = init;
                //for (var i = 0; i < 20/*data.Length*/; i++) // по алгоритму конечно надо ставить data.Length, но для моего алгоритма это значение 28, а лучшую скорость даёт 20
                //{
                //    result = CRC8_TABLE[result ^ data[i]];
                //}
                for (var i = 0; i < 5/*data.Length*/; i++) // по алгоритму конечно надо ставить data.Length, но для моего алгоритма это значение 28, а лучшую скорость даёт 20
                {
                    result = CRC8_TABLE[result ^ data[i * 4 + 0]];
                    result = CRC8_TABLE[result ^ data[i * 4 + 1]];
                    result = CRC8_TABLE[result ^ data[i * 4 + 2]];
                    result = CRC8_TABLE[result ^ data[i * 4 + 3]];
                }
                return result;
            }
        }
 
        static unsafe void SetBits(byte* dest, byte b5, byte b4, byte b3, byte b2, byte b1)
        {
            int* pDest = (int*)dest;
 
            *pDest = b5 | b4 << 8 | b3 << 16 | b2 << 24;
            pDest++;
 
            *pDest = b1 | b5 << 8 | b4 << 16 | b3 << 24;
            pDest++;
 
            *pDest = b2 | b1 << 8 | b5 << 16 | b4 << 24;
            pDest++;
 
            *pDest = b3 | b2 << 8 | b1 << 16 | b5 << 24;
            pDest++;
 
            *pDest = b4 | b3 << 8 | b2 << 16 | b1 << 24;
            pDest++;
 
            *pDest = b5 | b4 << 8 | b3 << 16 | b2 << 24;
            pDest++;
 
            *pDest = b1 | b5 << 8 | b4 << 16 | b3 << 24;
        }
 
        static unsafe void Main(string[] args)
        {
            int temp, old_percent = 0; // инициализация счетчиков и временных переменных
            int num1 = 0, num2 = 0;
 
            if (num1 >= num2)
                num2 = num1 + 1;
            else
                num2++; // по большому счёту нужно только если первое и второе значения менять, если ничего не трогать, то можно не обращать внимание
 
            ulong countN, countX, countIn = 0;
 
            byte hash = 0, crc = 0;
 
            byte* bitCounts = stackalloc byte[256];
 
            for (byte i = 0; i < 255; i++)
                bitCounts[i] = BitCount64(i);
 
            for (byte x1 = (byte)num1; x1 < (byte)num2; x1++) // первая переменная из матрицы 5х5 бит (условно верхняя)
            {
                countN = 0; countX = 0; // инициализация счетчиков
                var sw = Stopwatch.StartNew(); // запуск таймера
                for (byte x2 = 0; x2 < 32; x2++) // вторая переменная из матрицы
                {
                    // обновление элементов на форме, происходит только если данные изменились
                    temp = (int)((ulong)countN * (ulong)(x1 + 1) * 100 / (ulong)(Math.Pow(32, 4) * (num2 - num1))); // тут я набредил и больше не трогал, используется для вычисления шкалы ProgressBar, нормально работает для одного значения x1, по если x1 > 0 будет показывать криво
                                                                                                                    // обновление ProgressBar и Label с процентом
                                                                                                                    // порой достаточно посмотреть 50% от всей программы (это примерно 33% от всего объёма вычислений)
                    if (old_percent != temp)
                    {
                        Console.WriteLine(temp.ToString() + "%");
                        old_percent = temp;
                    }
 
                    for (byte x3 = 0; x3 < 32; x3++) // третья переменная из матрицы
                    {
                        for (byte x4 = 0; x4 < 32; x4++) // четвертая из матрицы
                        {
                            for (byte x5 = 0; x5 < 32; x5++) // пятая переменная
                            {
                                byte x1c = bitCounts[x1];
                                byte x2c = bitCounts[x2];
                                byte x3c = bitCounts[x3];
                                byte x4c = bitCounts[x4];
                                byte x5c = bitCounts[x5];
 
                                byte SumBits = (byte)(x1c + x2c + x3c + x4c + x5c); // сумма сумм бит
                                ref int tempIndex = ref countNidx[SumBits];
 
                                // заполнение массива в структуре
                                //byte[] bitsArray = new byte[] { x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c };
                                //byte* bitsArray = stackalloc byte[] { x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c, x2c, x1c, x5c, x4c, x3c };
 
                                //ref DimBitsS dimBits = ref DimBitsSN[tempIndex];
 
                                //dimBits = new DimBitsS(SumBits, bitsArray); // инициализация данных в структуре
 
                                //DimBitsSN[tempIndex] = new DimBitsS(SumBits, bitsArray); // инициализация данных в структуре
                                DimBitsSN[tempIndex] = new DimBitsS(SumBits); // инициализация данных в структуре
 
                                ref DimBitsS dimBits = ref DimBitsSN[tempIndex];
 
                                //fixed (byte* bits = bitsArray)
                                fixed (byte* bits = dimBits.Bits)
                                {
                                    SetBits(bits, x5c, x4c, x3c, x2c, x1c);
 
                                    //Unsafe.CopyBlock(bits, bitsArray, 28);
 
                                    // заполняем CRC8
                                    crc = dimBits.CRC8 = CRC8.Calculate(bits);
 
                                    // считаем и заполняем XOR хэш
                                    hash = 0;
                                    for (var h = 0; h < 3; h++)
                                        hash ^= bits[h];
                                    dimBits.Hash = hash;
                                }
 
                                //fixed (byte* bits = bitsArray)
                                //{
                                //    // заполняем CRC8
                                //    dimBits.CRC8 = CRC8.Calculate(bits);
 
                                //    // считаем и заполняем XOR хэш
                                //    for (var h = 0; h < 3; h++)
                                //        dimBits.Hash ^= bits[h];
                                //}
 
                                // запускаем основной цикл сравнения. Условие смотрит только за тем, чтобы проверка запускалась только если более одного значения посчитано
                                int dimIdxStart = DimIdx[SumBits];
 
                                if (countN > 0 && dimIdxStart != tempIndex)
                                {
                                    int dimIdxEnd = (dimIdxStart == tempIndex ? tempIndex + 1 : tempIndex);
 
                                    for (int i = dimIdxStart; i < dimIdxEnd; i++)
                                    {
                                        ref DimBitsS dimBits2 = ref DimBitsSN[i];
                                        //byte[] bitsArray2 = dimBits2.Bits;
 
                                        if (hash == dimBits2.Hash)
                                        {   // этот хэш простой XOR, число переменных выбирается
                                            // в BackgroundThreadFunc() до вызова For(Compare),
                                            // текущее значение выбрано опытным путём
                                            if (crc == dimBits2.CRC8) // функция взята с одной из тем Cyberforum
                                                                      // тоже не иду по всем byte[], значение подобрано
                                            {
                                                countIn++; // так увидим число входов, оно определяет продолжительность вычислений
 
                                                //fixed (byte* pBits1 = bitsArray)
                                                //fixed (byte* pBits2 = bitsArray2)
                                                fixed (byte* pBits1 = dimBits.Bits)
                                                fixed (byte* pBits2 = dimBits2.Bits)
                                                {
                                                    for (int n = 0; n < 24; n++)
                                                    {
                                                        // если прошли через хэши, то проверяем от частого к редкому и отлавливаем совпавшие
                                                        if (pBits1[n] == pBits2[n])
                                                        {
                                                            countX++; // число совпавших
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
 
                                countN++; // общее число итераций
                                tempIndex++; // движение указателей на данные
                            }
                        }
                    }
                }
                sw.Stop(); // таймер времени выполнения программы
                Console.WriteLine(countN + " : " + countIn + " : " + countX + " : " + sw.Elapsed);
            }
            Console.WriteLine("Цимес!!! Прес эни кий ту континью...");
            Console.ReadKey();
        }
    }
}
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
18.01.2019, 06:27  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
что проблема не в реализации, а в неверном выборе методологии решения
может быть. давайте озвучу идею:

у вас есть матрица 64х64, чтобы получить все комбинации бит в такой матрице нужно использовать 64 ulong переменные и производить инкремент каждой таким образом, чтобы перебрать все значения. это только даст доступ к исходным данным, теперь у нас есть всё, чтобы с этими данными работать. условно, есть черный ящик, который на входе принимает такие данные, делает вычисления и результаты сравнивает со всеми предыдущими, если находит совпадение, то обозначает это. Финал работы программы - как раз поиск таких совпадений.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
А у Вас, похоже, из-за недостатка знаний в программировании, не получается найти правильное решение.
Ну есть алгоритмическая часть и часть с непосредственной реализацией. Хромать может и то и другое. Но если с алгоритмом наверное будет сложно, так как я не раскрываю его особенности, то с реализацией должно быть проще, я в любом случае не претендую на лавры великого программиста.

Добавлено через 5 минут
Цитата Сообщение от maximka777 Посмотреть сообщение
Это потому что хэш размером в байт слишком мало, поэтому считает не правильно.
В моей реализации хэш не определяет конечное совпадение, он лишь отсеивает часть данных, поэтому считает правильно.

Цитата Сообщение от maximka777 Посмотреть сообщение
Значит нужно считать хэш.
проблема в том, что для всех хэшей не хватит оперативной памяти. Да и реализацию хэша, дающего уникальное значение я пока найти не смог, а то что находил - не мог прикрутить для себя.

Цитата Сообщение от maximka777 Посмотреть сообщение
А смысл ? Если хэши совпадают значит все равно будет.
сравнение хэшей каждого с каждым в любом случае потребуется.

я не вижу в вашей реализации расчета хэша.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,576
18.01.2019, 06:39
Цитата Сообщение от belalugoci Посмотреть сообщение
В моей реализации хэш не определяет конечное совпадение, он лишь отсеивает часть данных, поэтому считает правильно.
Почему тогда вы вычисляете 2 разных хэша, да еще и не от всех данных (у вас 28 байт), а лишь от их части (от 3 и от 20 байт...)? Как это может быть правильно?

Цитата Сообщение от belalugoci Посмотреть сообщение
Да и реализацию хэша, дающего уникальное значение я пока найти не смог
Хэш на то и хэш, всегда могут быть коллизии (разные данные генерируют одинаковый хэш). Чем меньше длинна хэша, тем выше вероятность возникновения коллизии... У вас хэш на 1 байт, вероятность коллизии очень высока...
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
18.01.2019, 06:42  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
К сожалению не самая быстрая версия, эта у меня работает примерно 2:30 минуты, а самая быстрая была 2:15, но что в ней было я уже вряд ли смогу вспомнить... Пробовал очень много разных вариантов...
ваше
1048576 : 2260798720 : 50585009280 : 00:03:27.6732082

моё
2260798720 : 50585009280 : 00:07:33.2875009

как видно - число итераций по проверке сокращено с 2,2 млрд до 1,1 млн. То есть в 2000 раз.
вы могли бы прокомментировать добавленные строки?
0
95 / 74 / 27
Регистрация: 13.08.2018
Сообщений: 203
18.01.2019, 06:43
Цитата Сообщение от belalugoci Посмотреть сообщение
В моей реализации хэш не определяет конечное совпадение, он лишь отсеивает часть данных, поэтому считает правильно.
У вас хэш служит для чего ? Чтобы проверить равны ли два массива друг другу ? Проблема в том что у СRС8 слишком много коллюзий , поэтому countIn будет посчитан не верно.
Здесь два способа подсчета countIn, угадайте почему считает пои разному ?
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
using System;
using System.Diagnostics;
 
namespace CalcBitsCL
{
    class Program
    {
        static object locker = new object();
 
        // это расчётные значения для работы с матрицей 5х5, но с фиксированным одним значение верхнего элемента, я тестировал со значением 0, но работает и с любым но одиночным значением
        // это большая оптимизация которая позволила резко сократить число операций, значения в массиве обозначают места для разных значений SumBits
        // идея в том, что сравнивать одни данные с другими имеет смысла только если суммы бит одинаковые, так мы сокращаем число итераций для For(Compare)
        public static readonly int[] DimIdx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
        public static int[] countNidx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
 
        public static DimBitsS[] DimBitsSN = new DimBitsS[1048576]; // число элементов матрицы 5х5, но для одного значения верхнего вектора, то есть формально 2 в двадцатой степени + 1
        public static byte SumBits = 0; // хранит сумму бит, является так же индексом для DimIdx и countNidx
 
        public static byte x1, x2, x3, x4, x5; // числа, используемые для отражения значений матрицы 5х5, x1 - верх, x5 - низ
 
        public static ulong countN = 0; public static ulong countIn = 0; public static ulong countX, old_countX; public static int num1, num2;
 
        public class DimBitsS
        {
            public byte[] Bits; // массив сумм бит
            public int Sum; // значение SumBits сохранённое во время расчета каждого элемента
            public byte Hash; // XOR хэш
            public byte CRC8; // CRC8
 
 
            public int zip;
            public DimBitsS(int _Sum) // инициализация
            {
                this.Sum = _Sum;
                this.Hash = 0;
                this.CRC8 = 0;
                this.Bits = new byte[28];
 
 
            }
        }
 
        public static void Compare(int y)
        {
        }
 
        public static byte BitCount(ulong value) // считаем число бит в переменной
        {
            ulong result = value - ((value >> 1) & 0x5555555555555555UL);
            result = (result & 0x3333333333333333UL) + ((result >> 2) & 0x3333333333333333UL);
            return (byte)(unchecked(((result + (result >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56);
        }
 
        static class CRC8 // расчет CRC8, нужно такое же, но на CRC32
        {
            static byte[] CRC8_TABLE = new byte[]{
                0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
                157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
                35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
                190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
                70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
                219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
                101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
                248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
                140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
                17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
                175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
                50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
                202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
                87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
                233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
                116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 };
 
            public static byte Calculate(byte[] data, byte init = 0)
            {
                byte result = init;
                for (var i = 0; i < 20/*data.Length*/; i++) // по алгоритму конечно надо ставить data.Length, но для моего алгоритма это значение 28, а лучшую скорость даёт 20
                {
                    result = CRC8_TABLE[result ^ data[i]];
                }
                return result;
            }
        }
 
        static void Main(string[] args)
        {
            int counter = 0;
            int cCRC = 0, cZip = 0;
 
            int temp, old_percent = 0; // инициализация счетчиков и временных переменных
            num1 = 0; num2 = 0;
            if (num1 >= num2) num2 = num1 + 1; else num2++; // по большому счёту нужно только если первое и второе значения менять, если ничего не трогать, то можно не обращать внимание
            for (x1 = (byte)num1; x1 < (byte)num2; x1++) // первая переменная из матрицы 5х5 бит (условно верхняя)
            {
                countN = 0; countX = 0; old_countX = 0; // инициализация счетчиков
                var sw = Stopwatch.StartNew(); // запуск таймера
                for (x2 = 0; x2 < 32; x2++) // вторая переменная из матрицы
                {
                    // обновление элементов на форме, происходит только если данные изменились
                    temp = (int)((ulong)countN * (ulong)(x1 + 1) * 100 / (ulong)(Math.Pow(32, 4) * (num2 - num1))); // тут я набредил и больше не трогал, используется для вычисления шкалы ProgressBar, нормально работает для одного значения x1, по если x1 > 0 будет показывать криво
                                                                                                                    // обновление ProgressBar и Label с процентом
                                                                                                                    // порой достаточно посмотреть 50% от всей программы (это примерно 33% от всего объёма вычислений)
                    if (old_percent != temp)
                    {
                        Console.WriteLine(temp.ToString() + "%");
                        old_percent = temp;
 
                        //Console.WriteLine(countIn);
                        Console.WriteLine($"cCRC : {cCRC}");
                        Console.WriteLine($"cZip : {cZip}");
 
                    }
 
 
 
                    if (counter++ > 3)
                    {
                        goto exit;
                    }
 
                    for (x3 = 0; x3 < 32; x3++) // третья переменная из матрицы
                    {
                        for (x4 = 0; x4 < 32; x4++) // четвертая из матрицы
                        {
                            for (x5 = 0; x5 < 32; x5++) // пятая переменная
                            {
                                SumBits = (byte)(BitCount(x1) + BitCount(x2) + BitCount(x3) + BitCount(x4) + BitCount(x5)); // сумма сумм бит
                                DimBitsSN[countNidx[SumBits]] = new DimBitsS(SumBits); // инициализация данных в структуре
 
                                // заполнение массива в структуре
                                DimBitsSN[countNidx[SumBits]].Bits[0] = (byte)BitCount(x5); // (byte) тут нужно только если поменять логику вычисления суммы бит
                                DimBitsSN[countNidx[SumBits]].Bits[1] = (byte)BitCount(x4); // можно придумать свои варианты суммирования, например
                                DimBitsSN[countNidx[SumBits]].Bits[2] = (byte)BitCount(x3); // ((x1) == 0 ? 0 : 1)
                                DimBitsSN[countNidx[SumBits]].Bits[3] = (byte)BitCount(x2); // в таком случае оптимизации нужно подстраивать под контекст
                                DimBitsSN[countNidx[SumBits]].Bits[4] = (byte)BitCount(x1); // например для моих алгоритвом расчёта я выяснил какие именно данные чаще меняются
                                DimBitsSN[countNidx[SumBits]].Bits[5] = (byte)BitCount(x5); // и отсортировал их в этом массиве, где 0 - часто, 27 - редко
                                DimBitsSN[countNidx[SumBits]].Bits[6] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[7] = (byte)BitCount(x3);
                                DimBitsSN[countNidx[SumBits]].Bits[8] = (byte)BitCount(x2);
                                DimBitsSN[countNidx[SumBits]].Bits[9] = (byte)BitCount(x1);
                                DimBitsSN[countNidx[SumBits]].Bits[10] = (byte)BitCount(x5);
                                DimBitsSN[countNidx[SumBits]].Bits[11] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[12] = (byte)BitCount(x3);
                                DimBitsSN[countNidx[SumBits]].Bits[13] = (byte)BitCount(x2);
                                DimBitsSN[countNidx[SumBits]].Bits[14] = (byte)BitCount(x1);
                                DimBitsSN[countNidx[SumBits]].Bits[15] = (byte)BitCount(x5);
                                DimBitsSN[countNidx[SumBits]].Bits[16] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[17] = (byte)BitCount(x3);
                                DimBitsSN[countNidx[SumBits]].Bits[18] = (byte)BitCount(x2);
                                DimBitsSN[countNidx[SumBits]].Bits[19] = (byte)BitCount(x1);
                                DimBitsSN[countNidx[SumBits]].Bits[20] = (byte)BitCount(x5);
                                DimBitsSN[countNidx[SumBits]].Bits[21] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[22] = (byte)BitCount(x3);
                                DimBitsSN[countNidx[SumBits]].Bits[23] = (byte)BitCount(x2);
                                DimBitsSN[countNidx[SumBits]].Bits[24] = (byte)BitCount(x1);
                                DimBitsSN[countNidx[SumBits]].Bits[25] = (byte)BitCount(x5);
                                DimBitsSN[countNidx[SumBits]].Bits[26] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[27] = (byte)BitCount(x3);
 
                                // заполняем CRC8
                                DimBitsSN[countNidx[SumBits]].CRC8 = CRC8.Calculate(DimBitsSN[countNidx[SumBits]].Bits);
                                //упаковка, по три бита на сумму
                                DimBitsSN[countNidx[SumBits]].zip = BitCount(x1) | BitCount(x2) << 3 | BitCount(x3) << 6 | BitCount(x4) << 9 | BitCount(x5) << 12;
 
                                // считаем и заполняем XOR хэш
                                for (var h = 0; h < 3; h++) DimBitsSN[countNidx[SumBits]].Hash ^= DimBitsSN[countNidx[SumBits]].Bits[h];
 
                                // запускаем основной цикл сравнения. Условие смотрит только за тем, чтобы проверка запускалась только если более одного значения посчитано
                                if (countN > 0 && DimIdx[SumBits] != countNidx[SumBits])
                                {
                                    for (var i = DimIdx[SumBits]; i < (DimIdx[SumBits] == countNidx[SumBits] ? countNidx[SumBits] + 1 : countNidx[SumBits]); i++)
                                    {
                                        if (DimBitsSN[countNidx[SumBits]].zip == DimBitsSN[i].zip) cZip++;
                                        if (DimBitsSN[countNidx[SumBits]].CRC8 == DimBitsSN[i].CRC8) cCRC++;
 
 
 
                                        //if (DimBitsSN[countNidx[SumBits]].zip == DimBitsSN[i].zip)
                                        //if (DimBitsSN[countNidx[SumBits]].Hash == DimBitsSN[i].Hash)
                                        {   // этот хэш простой XOR, число переменных выбирается
                                            // в BackgroundThreadFunc() до вызова For(Compare),
                                            // текущее значение выбрано опытным путём
                                            //if (DimBitsSN[countNidx[SumBits]].CRC8 == DimBitsSN[i].CRC8) // функция взята с одной из тем Cyberforum
                                            //                                                             // тоже не иду по всем byte[], значение подобрано
                                            {
                                                countIn++; // так увидим число входов, оно определяет продолжительность вычислений
                                                //for (var n = 0; n < 24; n++)
                                                //{
                                                //    if (DimBitsSN[countNidx[SumBits]].Bits[n] == DimBitsSN[i].Bits[n])
                                                //    // если прошли через хэши, то проверяем от частого к редкому и отлавливаем совпавшие
                                                //    {
                                                //        countX++; // число совпавших
                                                //    }
                                                //}
                                            }
                                        }
                                    }
                                }
 
                                countN++; // общее число итераций
                                countNidx[SumBits]++; // движение указателей на данные
                            }
                        }
                    }
                }
                
            }
 
 
            exit:
 
 
            Console.WriteLine("Цимес!!! Прес эни кий ту континью...");
            Console.ReadKey();
        }
    }
}
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,576
18.01.2019, 06:44
Цитата Сообщение от belalugoci Посмотреть сообщение
как видно - число итераций по проверке сокращено с 2,2 млрд до 1,1 млн. То есть в 2000 раз.
Ничего не сокращено. У вас значение 1048576 нигде не выводится вообще.
0
95 / 74 / 27
Регистрация: 13.08.2018
Сообщений: 203
18.01.2019, 06:56
Вот для примера два варианта, без СRC8. Первый обычный, второй ускоренный. Оба дают один и тот же ответ.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
using System;
using System.Diagnostics;
 
namespace CalcBitsCL
{
    class Program
    {
        static object locker = new object();
 
        // это расчётные значения для работы с матрицей 5х5, но с фиксированным одним значение верхнего элемента, я тестировал со значением 0, но работает и с любым но одиночным значением
        // это большая оптимизация которая позволила резко сократить число операций, значения в массиве обозначают места для разных значений SumBits
        // идея в том, что сравнивать одни данные с другими имеет смысла только если суммы бит одинаковые, так мы сокращаем число итераций для For(Compare)
        public static readonly int[] DimIdx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
        public static int[] countNidx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
 
        public static DimBitsS[] DimBitsSN = new DimBitsS[1048576]; // число элементов матрицы 5х5, но для одного значения верхнего вектора, то есть формально 2 в двадцатой степени + 1
        public static byte SumBits = 0; // хранит сумму бит, является так же индексом для DimIdx и countNidx
 
        public static byte x1, x2, x3, x4, x5; // числа, используемые для отражения значений матрицы 5х5, x1 - верх, x5 - низ
 
        public static ulong countN = 0; public static ulong countIn = 0; public static ulong countX, old_countX; public static int num1, num2;
 
        public class DimBitsS
        {
            public byte[] Bits; // массив сумм бит
            public int Sum; // значение SumBits сохранённое во время расчета каждого элемента
            public byte Hash; // XOR хэш
            public byte CRC8; // CRC8
 
 
            public int zip;
            public DimBitsS(int _Sum) // инициализация
            {
                this.Sum = _Sum;
                this.Hash = 0;
                this.CRC8 = 0;
                this.Bits = new byte[28];
 
 
            }
        }
 
        public static void Compare(int y)
        {
        }
 
        public static byte BitCount(ulong value) // считаем число бит в переменной
        {
            ulong result = value - ((value >> 1) & 0x5555555555555555UL);
            result = (result & 0x3333333333333333UL) + ((result >> 2) & 0x3333333333333333UL);
            return (byte)(unchecked(((result + (result >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56);
        }
 
        static class CRC8 // расчет CRC8, нужно такое же, но на CRC32
        {
            static byte[] CRC8_TABLE = new byte[]{
                0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
                157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
                35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
                190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
                70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
                219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
                101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
                248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
                140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
                17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
                175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
                50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
                202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
                87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
                233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
                116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 };
 
            public static byte Calculate(byte[] data, byte init = 0)
            {
                byte result = init;
                for (var i = 0; i < 20/*data.Length*/; i++) // по алгоритму конечно надо ставить data.Length, но для моего алгоритма это значение 28, а лучшую скорость даёт 20
                {
                    result = CRC8_TABLE[result ^ data[i]];
                }
                return result;
            }
        }
 
        static void Main(string[] args)
        {
            int counter = 0;
            int cCRC = 0, cZip = 0;
 
            int temp, old_percent = 0; // инициализация счетчиков и временных переменных
            num1 = 0; num2 = 0;
            if (num1 >= num2) num2 = num1 + 1; else num2++; // по большому счёту нужно только если первое и второе значения менять, если ничего не трогать, то можно не обращать внимание
            for (x1 = (byte)num1; x1 < (byte)num2; x1++) // первая переменная из матрицы 5х5 бит (условно верхняя)
            {
                countN = 0; countX = 0; old_countX = 0; // инициализация счетчиков
                var sw = Stopwatch.StartNew(); // запуск таймера
                for (x2 = 0; x2 < 32; x2++) // вторая переменная из матрицы
                {
                    // обновление элементов на форме, происходит только если данные изменились
                    temp = (int)((ulong)countN * (ulong)(x1 + 1) * 100 / (ulong)(Math.Pow(32, 4) * (num2 - num1))); // тут я набредил и больше не трогал, используется для вычисления шкалы ProgressBar, нормально работает для одного значения x1, по если x1 > 0 будет показывать криво
                                                                                                                    // обновление ProgressBar и Label с процентом
                                                                                                                    // порой достаточно посмотреть 50% от всей программы (это примерно 33% от всего объёма вычислений)
                    if (old_percent != temp)
                    {
                        Console.WriteLine(temp.ToString() + "%");
                        old_percent = temp;
 
                        
 
                    }
 
 
 
                    if (counter++ > 3)
                    {
                        goto exit;
                    }
 
                    for (x3 = 0; x3 < 32; x3++) // третья переменная из матрицы
                    {
                        for (x4 = 0; x4 < 32; x4++) // четвертая из матрицы
                        {
                            for (x5 = 0; x5 < 32; x5++) // пятая переменная
                            {
                                SumBits = (byte)(BitCount(x1) + BitCount(x2) + BitCount(x3) + BitCount(x4) + BitCount(x5)); // сумма сумм бит
                                DimBitsSN[countNidx[SumBits]] = new DimBitsS(SumBits); // инициализация данных в структуре
 
                                // заполнение массива в структуре
                                DimBitsSN[countNidx[SumBits]].Bits[0] = (byte)BitCount(x5); // (byte) тут нужно только если поменять логику вычисления суммы бит
                                DimBitsSN[countNidx[SumBits]].Bits[1] = (byte)BitCount(x4); // можно придумать свои варианты суммирования, например
                                DimBitsSN[countNidx[SumBits]].Bits[2] = (byte)BitCount(x3); // ((x1) == 0 ? 0 : 1)
                                DimBitsSN[countNidx[SumBits]].Bits[3] = (byte)BitCount(x2); // в таком случае оптимизации нужно подстраивать под контекст
                                DimBitsSN[countNidx[SumBits]].Bits[4] = (byte)BitCount(x1); // например для моих алгоритвом расчёта я выяснил какие именно данные чаще меняются
                                DimBitsSN[countNidx[SumBits]].Bits[5] = (byte)BitCount(x5); // и отсортировал их в этом массиве, где 0 - часто, 27 - редко
                                DimBitsSN[countNidx[SumBits]].Bits[6] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[7] = (byte)BitCount(x3);
                                DimBitsSN[countNidx[SumBits]].Bits[8] = (byte)BitCount(x2);
                                DimBitsSN[countNidx[SumBits]].Bits[9] = (byte)BitCount(x1);
                                DimBitsSN[countNidx[SumBits]].Bits[10] = (byte)BitCount(x5);
                                DimBitsSN[countNidx[SumBits]].Bits[11] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[12] = (byte)BitCount(x3);
                                DimBitsSN[countNidx[SumBits]].Bits[13] = (byte)BitCount(x2);
                                DimBitsSN[countNidx[SumBits]].Bits[14] = (byte)BitCount(x1);
                                DimBitsSN[countNidx[SumBits]].Bits[15] = (byte)BitCount(x5);
                                DimBitsSN[countNidx[SumBits]].Bits[16] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[17] = (byte)BitCount(x3);
                                DimBitsSN[countNidx[SumBits]].Bits[18] = (byte)BitCount(x2);
                                DimBitsSN[countNidx[SumBits]].Bits[19] = (byte)BitCount(x1);
                                DimBitsSN[countNidx[SumBits]].Bits[20] = (byte)BitCount(x5);
                                DimBitsSN[countNidx[SumBits]].Bits[21] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[22] = (byte)BitCount(x3);
                                DimBitsSN[countNidx[SumBits]].Bits[23] = (byte)BitCount(x2);
                                DimBitsSN[countNidx[SumBits]].Bits[24] = (byte)BitCount(x1);
                                DimBitsSN[countNidx[SumBits]].Bits[25] = (byte)BitCount(x5);
                                DimBitsSN[countNidx[SumBits]].Bits[26] = (byte)BitCount(x4);
                                DimBitsSN[countNidx[SumBits]].Bits[27] = (byte)BitCount(x3);
 
                                // заполняем CRC8
                                DimBitsSN[countNidx[SumBits]].CRC8 = CRC8.Calculate(DimBitsSN[countNidx[SumBits]].Bits);
                                //упаковка, по три бита на сумму
                                DimBitsSN[countNidx[SumBits]].zip = BitCount(x1) | BitCount(x2) << 3 | BitCount(x3) << 6 | BitCount(x4) << 9 | BitCount(x5) << 12;
 
                                // считаем и заполняем XOR хэш
                                for (var h = 0; h < 3; h++) DimBitsSN[countNidx[SumBits]].Hash ^= DimBitsSN[countNidx[SumBits]].Bits[h];
 
                                // запускаем основной цикл сравнения. Условие смотрит только за тем, чтобы проверка запускалась только если более одного значения посчитано
                                if (countN > 0 && DimIdx[SumBits] != countNidx[SumBits])
                                {
                                    for (var i = DimIdx[SumBits]; i < (DimIdx[SumBits] == countNidx[SumBits] ? countNidx[SumBits] + 1 : countNidx[SumBits]); i++)
                                    {
 
 
                                        if (DimBitsSN[countNidx[SumBits]].zip == DimBitsSN[i].zip)
                                        //if (DimBitsSN[countNidx[SumBits]].Hash == DimBitsSN[i].Hash)
                                        {   // этот хэш простой XOR, число переменных выбирается
                                            // в BackgroundThreadFunc() до вызова For(Compare),
                                            // текущее значение выбрано опытным путём
                                            //if (DimBitsSN[countNidx[SumBits]].CRC8 == DimBitsSN[i].CRC8) // функция взята с одной из тем Cyberforum
                                            //                                                             // тоже не иду по всем byte[], значение подобрано
                                            {
                                                countIn++; // так увидим число входов, оно определяет продолжительность вычислений
                                                //for (var n = 0; n < 24; n++)
                                                //{
                                                //    if (DimBitsSN[countNidx[SumBits]].Bits[n] == DimBitsSN[i].Bits[n])
                                                //    // если прошли через хэши, то проверяем от частого к редкому и отлавливаем совпавшие
                                                //    {
                                                //        countX++; // число совпавших
                                                //    }
                                                //}
                                            }
                                        }
                                    }
                                }
 
                                countN++; // общее число итераций
                                countNidx[SumBits]++; // движение указателей на данные
                            }
                        }
                    }
                }
                
            }
 
 
            exit:
 
            Console.WriteLine(countIn);
 
            Console.WriteLine("Цимес!!! Прес эни кий ту континью...");
            Console.ReadKey();
        }
    }
}


Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
 
namespace CalcBitsCL
{
    class Program
    {
        static object locker = new object();
 
        // это расчётные значения для работы с матрицей 5х5, но с фиксированным одним значение верхнего элемента, я тестировал со значением 0, но работает и с любым но одиночным значением
        // это большая оптимизация которая позволила резко сократить число операций, значения в массиве обозначают места для разных значений SumBits
        // идея в том, что сравнивать одни данные с другими имеет смысла только если суммы бит одинаковые, так мы сокращаем число итераций для For(Compare)
        public static readonly int[] DimIdx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
        public static int[] countNidx = { 0, 1, 21, 211, 1351, 6196, 21700, 60460, 137980, 263950, 431910, 616666, 784626, 910596, 988116, 1026876, 1042380, 1047225, 1048365, 1048555, 1048575, 1048576, 1048576, 1048576, 1048576, 1048576, 1048576 };
 
        public static DimBitsS[] DimBitsSN = new DimBitsS[1048576]; // число элементов матрицы 5х5, но для одного значения верхнего вектора, то есть формально 2 в двадцатой степени + 1
        public static byte SumBits = 0; // хранит сумму бит, является так же индексом для DimIdx и countNidx
 
        public static byte x1, x2, x3, x4, x5; // числа, используемые для отражения значений матрицы 5х5, x1 - верх, x5 - низ
 
        public static ulong countN = 0; public static ulong countIn = 0; public static ulong countX, old_countX; public static int num1, num2;
 
        public class DimBitsS
        {
            public byte[] Bits; // массив сумм бит
            public int Sum; // значение SumBits сохранённое во время расчета каждого элемента
            public byte Hash; // XOR хэш
            public byte CRC8; // CRC8
            public int zip;
            public DimBitsS(int _Sum) // инициализация
            {
                this.Sum = _Sum;
                this.Hash = 0;
                this.CRC8 = 0;
                this.Bits = new byte[28];
                zip = 0;
            }
        }      
 
        public static byte BitCount(ulong value) // считаем число бит в переменной
        {
            ulong result = value - ((value >> 1) & 0x5555555555555555UL);
            result = (result & 0x3333333333333333UL) + ((result >> 2) & 0x3333333333333333UL);
            return (byte)(unchecked(((result + (result >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56);
        }
 
        class C
        {
            public int Begin, End, Zip;
            public C(int begin, int end, int zip)
            {
                Begin = begin;
                End = end;
                Zip = zip;
            }           
 
            public override string ToString()
            {
                return $"{Begin} : {End} : {Zip}";
            }
        }
 
        static void Main(string[] args)
        {
            int counter = 0;
 
            var ranges = new List<C>();
 
            int temp, old_percent = 0; // инициализация счетчиков и временных переменных
            num1 = 0; num2 = 0;
            if (num1 >= num2) num2 = num1 + 1; else num2++; // по большому счёту нужно только если первое и второе значения менять, если ничего не трогать, то можно не обращать внимание
            for (x1 = (byte)num1; x1 < (byte)num2; x1++) // первая переменная из матрицы 5х5 бит (условно верхняя)
            {
                countN = 0; countX = 0; old_countX = 0; // инициализация счетчиков
                var sw = Stopwatch.StartNew(); // запуск таймера
                for (x2 = 0; x2 < 32; x2++) // вторая переменная из матрицы
                {
                    // обновление элементов на форме, происходит только если данные изменились
                    temp = (int)((ulong)countN * (ulong)(x1 + 1) * 100 / (ulong)(Math.Pow(32, 4) * (num2 - num1))); // тут я набредил и больше не трогал, используется для вычисления шкалы ProgressBar, нормально работает для одного значения x1, по если x1 > 0 будет показывать криво
                                                                                                                    // обновление ProgressBar и Label с процентом
                                                                                                                    // порой достаточно посмотреть 50% от всей программы (это примерно 33% от всего объёма вычислений)
                    if (old_percent != temp)
                    {
                        Console.WriteLine(temp.ToString() + "%");
                        old_percent = temp;
 
                    }
 
                    if (counter++ > 3)
                    {
                        goto exit;
                    }
 
                    for (x3 = 0; x3 < 32; x3++) // третья переменная из матрицы
                    {
                        for (x4 = 0; x4 < 32; x4++) // четвертая из матрицы
                        {
                            for (x5 = 0; x5 < 32; x5++) // пятая переменная
                            {
                                SumBits = (byte)(BitCount(x1) + BitCount(x2) + BitCount(x3) + BitCount(x4) + BitCount(x5)); // сумма сумм бит
 
                                DimBitsSN[countNidx[SumBits]] = new DimBitsS(SumBits); // инициализация данных в структуре                             
 
 
                                DimBitsSN[countNidx[SumBits]].zip = BitCount(x1) | BitCount(x2) << 3 | BitCount(x3) << 6 | BitCount(x4) << 9 | BitCount(x5) << 12;                               
 
                                // запускаем основной цикл сравнения. Условие смотрит только за тем, чтобы проверка запускалась только если более одного значения посчитано
                                if (countN > 0 && DimIdx[SumBits] != countNidx[SumBits])
                                {
                                    ranges.Add(new C(
                                        DimIdx[SumBits],
                                        (DimIdx[SumBits] == countNidx[SumBits] ? countNidx[SumBits] + 1 : countNidx[SumBits]),
                                        DimBitsSN[countNidx[SumBits]].zip)
                                        );
                                }
 
                                countN++; // общее число итераций
                                countNidx[SumBits]++; // движение указателей на данные
                            }
                        }
                    }
                }                
            }
 
            exit:           
 
            foreach (var group in ranges.OrderBy(x => x.Begin).GroupBy(x => x.Begin))
            {
                int i = group.Key;
 
                ulong[] data = new ulong[1 << 16];
 
                foreach (var item in group.OrderBy(x => x.End))
                {
                    for (; i < item.End; i++)
                    {
                        data[DimBitsSN[i].zip]++;
                    }
                    countIn += data[item.Zip];
                }
            }
 
            Console.WriteLine(countIn);
 
            Console.WriteLine("Цимес!!! Прес эни кий ту континью...");
            Console.ReadKey();
        }
    }
}
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
18.01.2019, 11:00  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
Почему тогда вы вычисляете 2 разных хэша
так как у меня нет реализации хэша, дающего уникальные значения, то я часть данных отсеиваю хэшем с большим числом коллизий, а потом делаю XOR по самым частым данным (они в начале списка).
вы можете убрать мои оптимизации и применять только свои.

Цитата Сообщение от maximka777 Посмотреть сообщение
У вас хэш служит для чего ? Чтобы проверить равны ли два массива друг другу ?
Типа того, на самом деле он только отсеивает неравные, а равным не доверяет и всё равно перепроверяет.

Цитата Сообщение от maximka777 Посмотреть сообщение
Проблема в том что у СRС8 слишком много коллюзий , поэтому countIn будет посчитан не верно.
вы не так понимаете countIn - это не число ВЕРНЫХ хэшей, это число итераций после того, как прошли оптимизации, чем меньше это число, тем лучше.

Цитата Сообщение от maximka777 Посмотреть сообщение
угадайте почему считает пои разному ?
Зачем угадывать? Вы считаете абсолютно разные вещи.

Цитата Сообщение от Someone007 Посмотреть сообщение
Ничего не сокращено. У вас значение 1048576 нигде не выводится вообще.
ааа, увидел. В любом случае был бы рад комментариям по коду.

Цитата Сообщение от maximka777 Посмотреть сообщение
Вот для примера два варианта, без СRC8. Первый обычный, второй ускоренный. Оба дают один и тот же ответ.
CRC8 не является обязательным, его можно и убрать. Во втором листинге у вас отсутствует код заполнения Bits[].
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16158 / 11278 / 2891
Регистрация: 21.04.2018
Сообщений: 33,164
Записей в блоге: 2
18.01.2019, 12:44
Цитата Сообщение от belalugoci Посмотреть сообщение
у вас есть матрица 64х64, чтобы получить все комбинации бит в такой матрице нужно использовать 64 ulong переменные и производить инкремент каждой таким образом, чтобы перебрать все значения
Даже без дальнейших операций, уже выполнение этого потребует недопустимо большого времени. Вам фактически надо перебрать 128 битовое число. Сейчас с этим не справится не один суперкомпьютер, ни их сеть. Надежда только на квантовые компьютеры - есть слухи, что IBM такой запустила.
Вам надо менять теоретическую часть. В лоб такую задачу не решить. Время решения задачи у Вас пропорционально четырём в степени стороны матрицы. Поэтому придумывать способы оптимизации для размеров 5х5, 10х10, 15х15 и т.д. - смысла нет. Конечное время, для 64х64 всё равно останется недопустимо большим.

Добавлено через 9 минут
Цитата Сообщение от belalugoci Посмотреть сообщение
у вас есть матрица 64х64
Уточняю, на всякий случай. Исходная матрица - это матрица бит?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,576
18.01.2019, 18:03
Цитата Сообщение от belalugoci Посмотреть сообщение
так как у меня нет реализации хэша, дающего уникальные значения
Не бывает таких хэшей. Всегда есть вероятность коллизии.


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

Так же сравнивать по 1 байту гораздо медленней, чем скажем по 4 или 8...

Вот по идее неплохой шэш, есть 2 варианта на 32 и 64 бита, всяко лучше чем ваш 8 битный...
https://github.com/differentra... /XXHash.cs
Или такой на 128 бит...
http://blog.teamleadnet.com/20... rithm.html

Цитата Сообщение от belalugoci Посмотреть сообщение
В любом случае был бы рад комментариям по коду.
Ну а что там комментировать...
Убраны повторяющиеся вызовы BitCount (они в конечном итоге были вообще заменены простым массивом...).
Уменьшено обращение к полям класса (доступ к локальным переменным быстрее), некоторые значения так же сохранены в локальные переменные по той же причине.
В нескольких местах использован unsafe код, чтобы избежать лишних проверок на выход за границы массива...
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
18.01.2019, 21:18  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вам фактически надо перебрать 128 битовое число
неа, 64х64 это не 128, это 4096 битовое число, то есть 24096

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Уточняю, на всякий случай. Исходная матрица - это матрица бит?
да

Цитата Сообщение от Someone007 Посмотреть сообщение
Не бывает таких хэшей. Всегда есть вероятность коллизии.
верно, я скорее о том, какое число выборок останется. главное чтобы хэш функция при одинаковых исходных данных давала одинаковый хэш, иначе зачем она вообще нужна )

Цитата Сообщение от Someone007 Посмотреть сообщение
Так же не понятно чем применение хэша может ускорить ваши вычисления, т.к. для вычисления хэша нужно пройтись по всем байтам, не проще ли сразу без всяких хэшей это делать?
задача состоит из двух частей, первая - это 24096 итераций по вычислению и вторая - 2\sum_{0}^{4096} итерацией (формула почему-то не рисуется) проверок каждого с каждым. Всё что вычисляется в первой части будет предпочтительнее чем всё что во второй, потому что элементарно будет делаться меньшее число раз. Число countIn как раз показывает такое число итераций.

Так же сравнивать по 1 байту гораздо медленней, чем скажем по 4 или 8...
В другой теме был дан код unsafe функции по сравнению, там шел процесс сравнения по 8 бит за раз. Я читал про этот метод, считается весьма производительным. Но у меня никакой прибавки "в разы" он не давал.

Убраны повторяющиеся вызовы BitCount
В этом нет смысла, так как они указаны для примера. В оригинальном коде все 28 Bits[] уникальны.

Уменьшено обращение к полям класса (доступ к локальным переменным быстрее), некоторые значения так же сохранены в локальные переменные по той же причине.
То есть вместо
int a = DimBits[x].Hash;
если написать
int hash= DimBits[x].Hash;
int a = hash;
это будет быстрее? Мне кажется это не так, первые строки в обоих вариантах одинаковые, а во втором варианте ещё одна операция добавляется.
Или вы про то, что в цикле лучше обращаться к локальной переменной?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16158 / 11278 / 2891
Регистрация: 21.04.2018
Сообщений: 33,164
Записей в блоге: 2
18.01.2019, 21:41
Цитата Сообщение от belalugoci Посмотреть сообщение
неа, 64х64 это не 128, это 4096 битовое число, то есть 24096
То есть состояние каждой ячейки это уникальный независимый бит?
Если да, то решать такую задачу перебором ближайшие несколько тысяч лет не научатся.
Надо упрощать как-то, сводить до реализуемых значений.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
18.01.2019, 23:12  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
То есть состояние каждой ячейки это уникальный независимый бит?
да

Цитата Сообщение от Элд Хасп Посмотреть сообщение
решать такую задачу перебором ближайшие несколько тысяч лет не научатся.
пока цель добраться до 8х8, а потом 16х16. Так сказать сформировать BigData массив, с которым уже можно работать. За два месяца я сам и с вашей помощью оптимизировали работу программы с 7 часов до 4 минут для 4х5 матрицы, то есть 8х8 уже подходит к границе разумного.
Прямо сейчас переделал код под ваши (всех участников) рекомендации, чуть позже еще CRC32 попробую прикрутить. НО даже этих небольших изменений было достаточно для еще 12% прироста в скорости. Я думаю от 20 до 50% ещё есть реальная возможность улучшить, а это уже 2-2,5 минуты. Через месяц-два у меня будет своё чуть более производительное железо, что даст 1,5-2 минуты для 4х5 и я попробую уже 8х8.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Надо упрощать как-то, сводить до реализуемых значений.
Читаю про CUDA, посмотрю можно ли как-то использовать видеокарту.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16158 / 11278 / 2891
Регистрация: 21.04.2018
Сообщений: 33,164
Записей в блоге: 2
18.01.2019, 23:30
Цитата Сообщение от belalugoci Посмотреть сообщение
что даст 1,5-2 минуты для 4х5 и я попробую уже 8х8.
Если я вас правильно понял, то вычислительные затраты определяются перебором всех ячеек матрицы 0-1. То есть 4х5 - это перебор 2^20 комбинаций.
В таком случае 8^8 - это 2^64 комбинаций. Даже если Вы сможете на новом железе, на графической карте вычислять 4х5 за 1 секунду для 8^8 потребуется полмиллиона лет. Даже если Вы будете считать это на суперкомпьютере для это потребуются годы. И это только для варианта 8х8.

Добавлено через 4 минуты
В Вашей методике расчёта даже варианты 63х63 и 64х64 отличаются в вычислительной сложности в 2^127 раз.

Добавлено через 1 минуту
Меняйте саму теорию методики расчёта. В лоб это в принципе не решить никогда!
Ну, может, пока только фантастические, квантовые компьютеры.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
18.01.2019, 23:33  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
потребуется полмиллиона лет
на самом деле 585 млрд лет. Не будем так пессимистичны.
0
95 / 74 / 27
Регистрация: 13.08.2018
Сообщений: 203
18.01.2019, 23:36
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Ну, может, пока только фантастические, квантовые компьютеры.
У IBM есть квантовый компьютер онлайн, можно на не попробовать.
0
 Аватар для belalugoci
475 / 294 / 29
Регистрация: 01.06.2018
Сообщений: 3,676
19.01.2019, 10:49  [ТС]
Цитата Сообщение от maximka777 Посмотреть сообщение
У IBM есть квантовый компьютер онлайн, можно на не попробовать.
проблема не только вычислительная. нужно хранить 35*264 байт данных.

Добавлено через 11 часов 10 минут
Цитата Сообщение от Someone007 Посмотреть сообщение
Ну а что там комментировать...
Убраны повторяющиеся вызовы BitCount (они в конечном итоге были вообще заменены простым массивом...).
Уменьшено обращение к полям класса (доступ к локальным переменным быстрее), некоторые значения так же сохранены в локальные переменные по той же причине.
В нескольких местах использован unsafe код, чтобы избежать лишних проверок на выход за границы массива...
Там где можно в моей реализации взял ваши изменения. На моем старом Q9300 мой код исполнялся 17 минут, сейчас 7 минут 5 секунд. Это в многопотоке.
Основные изменения - unsafe обращение к массивами, замена вызовов локальными переменными.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.01.2019, 10:49

преобразование ref byte в byte[] или в IntPtr без использования неуправляемого кода
есть COM интерфейс с методом: virtual /* */ HRESULT STDMETHODCALLTYPE OnReceivePacket( /* */ long dwSize, ...

Как перевести byte[] или переменную типа IntPtr к типу byte[] (ассемблерные инструкции)?
Наткнулась на проблему, нужно перевести тип IntPtr в массив ассемблерной инструкции. Вот пример кода, который нужно справить: ...

Пердача byte[] COM-функции, ожидающей ref byte
Привет, наше приложение в C# использует несколько COM-интерфейсов. В одном из них есть метод, которому передается ref byte : ...

wav byte[] в flac byte[]
Ситуация такая: С микрофона каждую 0.1 сек идет byte где то по 3к значений. Если я пишу его в файл то получается как бы wav файл....

Linq преобразовать DataTable в Dictionary<int,List<int>
Добрый день, помогите пожалуйста, со следующей задачей. Есть DataTable состоящий из 2 колонок: первая колонка id группы, вторая колонка id...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
Вангую, что это не пройдёт модерацию, и на неделе я запущу свой сервер.
Hrethgir 19.07.2026
Эта публикация сейчас в песочнице и ждёт приглашения. https:/ / habr. com/ ru/ sandbox/ 295048/ начало и оглавление - Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование. . .
сукцессия 33. открытые вопросы от клауде
anaschu 19.07.2026
"Что накопилось за эту часть А — тринадцать правок, из которых шесть пришли из ваших вопросов и каждая оказалась реальной ошибкой, а не калибровкой: односторонний симбиоз, отсутствующий листопад,. . .
32 сукцессия
anaschu 19.07.2026
сукцессия 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не «подкручивает» сходимость —. . .
сукцессия 31: модель микоризы - это модель ещё нескольких явлений, социальных и экономических
anaschu 18.07.2026
Теория «Всего»: апдейт v1. 1. 2 — 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не. . .
сукцессия 30. Массив проверяющих друг друга моделей
anaschu 18.07.2026
Архитектура сети взаимопроверяющих моделей микоризной сукцессии (v2. 0) Развитие тензорного ОДУ-ядра и создание кросс-платформенного калибровочного полигона Уважаемые коллеги! В продолжение. . .
Грибы - это женщины, деревья - это мужчины. Анти инь янь для союза мужчины и женщины.
anaschu 18.07.2026
ГЛАВНЫЙ НАУЧНО-ФИЛОСОФСКИЙ ВЫВОД: Сексуально-Репродуктивный Капитализм против Государства Моногамии Коллеги, мы вышли на финишную прямую 20-мерного ОДУ-моделирования вековой сукцессии (ветка. . .
Текстовый слайдер с нумерацией страниц и кроссбраузерность.
russiannick 18.07.2026
Один мой друг написал текстовый слайдер с нумерацией страниц. Сегодня я расскажу как он умудрился подружить его с кроссбраузерностью. Очевидно сложно угодить с шириной каждому браузеру. Один крадет. . .
Грибы - это мемы, дерево - это человек. Применение микоризной модели к теории меметики Докинза.
anaschu 18.07.2026
Меметический изоморфизм теории «всего»: Грибная сукцессия как модель эволюции идей Докинза Базовый код системы ОДУ микоризной сукцессии описывает не просто биологию, а универсальную. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru