|
|
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Aleksandr Sharahov1. Заменить деление умножением, умножать на обратный. Путаешь. Вычитание можно заменить на сложение с обратным, но к делению это неприменимо. Aleksandr Sharahov2. Заменить деление вычитанием, делить в столбик. Быстрее не станет, слишком много операций. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 15:12 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
На похмельную голову вышло как-то так: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Сама IntToText(та самая самоделка): Код: pascal 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. Погонял на числах, вроде работает. По скорости отпишу после 9го числа, все тесты на работе) Всем спасибо за советы! Код ещё в порядок надо будет привести и сделать owerlode, но это мелочи. Ещё раз благодарен всем за помощь! и с прошедшими и наступающими) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 15:20 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Dima TAleksandr Sharahov1. Заменить деление умножением, умножать на обратный. Путаешь. Вычитание можно заменить на сложение с обратным, но к делению это неприменимо. Не путаю. 1. Можно погуглить на тему "замена целочисленного деления умножением" или глянуть Уоррена, например. 2. Можно посмотреть, во что преобразует деление на 10 любой сишный компилятор. 3. До кучи тут есть немного http://guildalfa.ru/alsha/node/31 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 15:22 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Midgard90, внезапно переполнение: val : int64; n : integer; n := val div 1000000000; ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 15:45 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Посмотрел во что мой код скомпилировался, похоже компилятор MSVС сам заменил деление Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 16:11 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Код: plaintext 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. аргумент беззнаковый, на выходе лидирующие нули ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 16:37 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Странно) скорее всего старая дельфа топорная, потому как в их исходниках IntToStr похожий код с делением, что на выходе в асме не смотрел, но работает. В новой всё заменено уже сями и fastcall, да и работать в новой проще. Насчёт переполнения думаю не проблема, разбить не на 2 а на 4 части и каждую прогнать, потом сложить PCharы. Конечный вариант кину после 9го) работы для праздников хватит)) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 16:39 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
погонял. переполнения не встретил. приведи пример? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 02:09 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Aleksandr SharahovПётр СедовЕсли Delphi-йский компилятор для кода типа «n mod 10 ... n div 10» генерирует 2 инструкции div, то да :). если немного подумать, а не переводить стрелки на компилятор, то легко понять, что есть алгоритм с одним делением: d:=n div 10; r:=n - d * 10;Деление, умножение, вычитание. Три операции в машинном коде. При том, что достаточно одной, потому что x86-инструкция div выдаёт 2 результата: частное (в регистре eax) и остаток (в регистре edx), и хороший оптимизирующий компилятор должен этим пользоваться. Ну это как для кода «cos(x) ... sin(x)» генерировать одну инструкцию fsincos. Или для кода «(n << 16) | (n >> 16)» генерировать одну инструкцию циклического сдвига. А так-то понятно, что руками много чего можно сделать, например беззнаковое деление на степень двойки заменить на битовый сдвиг. Aleksandr SharahovПётр СедовМне удалось разбить только на 3 части. если проявить смекалку, например, перейти к беззнаковым числам и поработать со старшими битами и с обратными числами, то удается получить 2 части.int64 (максимум 19 цифр) можно разбить на 3 части (9 цифр, 9 цифр, 1 цифра) или на 4 части (5 цифр, 5 цифр, 5 цифр, 4 цифры). А на 2 части как разбить? (чтобы каждая часть гарантированно влезала в 32 бита) ИзопропилПётр Седов Код: pascal 1. 2. этого можно избежать изначально заполнив весь буфер нулямиДа, но длинные последовательности нулей редко встречаются, так что этим особо не ускоримся. Изопропил Код: plaintext 1. Проверил, работает правильно. Пара мелочей: Изопропил Код: plaintext 1. Похоже, не нужно. Если работаем со строками в C-шном стиле, то хорошо бы писать завершающий нулевой char: Код: plaintext 1. 2. 3. 4. 5. Я переписал ваш код на Pascal: Код: pascal 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. Midgard90погонял. переполнения не встретил. приведи пример?Ваш код: Midgard90 Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Если value = val = 9223372036854775807 (максимальное значение), то: val div 1000000000 = 9223372036 -- не влезает в integer (максимальное значение -- 2147483647). И в cardinal тоже не влезает (максимальное значение -- 4294967295). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 05:21 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Пётр СедовДеление, умножение, вычитание. Три операции в машинном коде. При том, что достаточно одной, потому что x86-инструкция div выдаёт 2 результата: частное (в регистре eax) и остаток (в регистре edx) Ты же понимаешь, что мое замечание касалось ненужности второго деления в твоем коде? И компилятор тут ни при чем. На самом деле не нужно и первое деление. Или нужно, но другое. Пётр Седовint64 (максимум 19 цифр) можно разбить на 3 части (9 цифр, 9 цифр, 1 цифра) или на 4 части (5 цифр, 5 цифр, 5 цифр, 4 цифры). А на 2 части как разбить? (чтобы каждая часть гарантированно влезала в 32 бита) Идея в том, чтобы отделить часть работы, которая формально соответствует очень маленькой третьей части данных, и выполнить эту часть работы независимо от обработки двух других больших кусков. Ну, когда, например, мы обрабатываем знак числа, мы же не называем это третьей частью данных, хотя формально так оно и есть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 09:22 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Код: plaintext 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. быстрее, чем библиотечный _ui64toa глядя на ассемблерное порождение - сильно больше на 32 бит x86 - вряд ли получится выжать Код: sql 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 11:33 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Еще можно itoa и atoi собрать в obj файл на с++ и затем использовать в проекте на Delphi. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 22:43 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
__Avenger__в obj файл на с++ что означает этот набор слов? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 23:21 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Изопропил__Avenger__в obj файл на с++ что означает этот набор слов? Скомпилировать c++ файл в obj файл, а затем использовать его в delphi через директиву {$LINK *.obj}. ZLib так например в дельфи подключен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 23:27 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
__Avenger__Изопропилпропущено... что означает этот набор слов? Скомпилировать c++ файл в obj файл, а затем использовать его в delphi через директиву {$LINK *.obj}. ZLib так например в дельфи подключен. ну лучше С, а не С++ и внимательно следить чтоб из рантайма лишку не зацепить. проще dll сделать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 23:46 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Изопропил Код: plaintext 1. 2. 3. 4. Код: sql 1. 2. 3. 4. 5. 6. 7. Visual C++ сгенерировал такой код, как предлагал Aleksandr Sharahov: деление, умножение, вычитание. Хотя вполне мог сгенерировать код типа: edx:eax ← _vq div 100000 v3 ← eax (частное) v2 ← edx (остаток) Изопропил Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. ... глядя на ассемблерное порождение - сильно больше на 32 бит x86 - вряд ли получится выжатьТут одинаковые операции делаются, поэтому если писать на ассемблере, то можно попытаться ускориться за счёт использования MMX-инструкций, которые работают с 32-битными числами, упакованными в 64-битные регистры: paddd -- делает параллельно два сложения psubd -- делает параллельно два вычитания pslld -- делает параллельно два битовых сдвига влево psrld -- делает параллельно два битовых сдвига вправо pand -- делает параллельно два битовых and (на самом деле, просто 64-битный and) А вот умножения нормального нет, поэтому умножение на f1_10001 придётся делать обычными инструкциями, а умножение на 10 заменить на «(n << 3) + (n << 1)». Кстати, Visual C++ умножение на 10 делает так: Изопропил Код: sql 1. 2. Изопропил Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Зачем Visual C++ делает «ecx ← buf + 19» на каждой итерации цикла? Это достаточно сделать один раз до цикла. А если писать на ассемблере самому, то тут вообще, насколько я понимаю, весь цикл можно записать одной инструкцией: repe scasb. Изопропилбыстрее, чем библиотечный _ui64toaКруто. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 06:57 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Пётр СедовVisual C++ сгенерировал такой код, как предлагал Aleksandr Sharahov: деление, умножение, вычитание. Хотя вполне мог сгенерировать код типа: edx:eax ← _vq div 100000 v3 ← eax (частное) v2 ← edx (остаток) uint64/uint32 - частное может не уместиться в uint32, потому нельзя одной командой, переполнение может случиться - потому - деление "столбиком" (см исходники ulldiv.asm, ulldrvm.asm) Пётр СедовЗачем Visual C++ делает «ecx ← buf + 19» на каждой итерации цикла? inc и lea выполнятся одновременно, потери производительности не будет, хотя действительно странно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 09:49 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
SSE2 версия Код: plaintext 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. не ускоряет ( по крайней мере на тех CPU, что использовал) а что до "крутости" - _ui64toa работает с произвольным основанием системы счисления и скорость зависит от количества цифр, возня может иметь смысл, если часто преобразовывать большие числа приходится. в конечном итоге - преобразование двоичного в десятичное вряд ли является узким местом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 10:08 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Если нужно обрабатывать многоцифр, то нужно их обрабатывать параллельно. И добро пожаловать в волшебный мир SIMD. Остальное пырхание не стоит внимания. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 10:10 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
SiemarglИ добро пожаловать в волшебный мир SIMD. он не настолько волшебен, как иногда кажется. ускорь _ui64toa с помощью SSE4, а там и будем выводы делать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 11:07 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Таак... с переполнением разобрался, потом нашёл ещё несколько багов: прошлая функция не дописывала нули, например: 9000000001000000001 на выходе 911)). В общем вышло как-то так: Код: pascal 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. Не думаю теперь что она быстрее IntToStr или предложенной ранее чисто дельфийской)) Завтра на скорость будем тестить с профитом по ядрам. Как её укоротить или оптимизировать уже что-то не соображаю. И масса локальных напрягает. Не функция а костыль, но работает)) Если есть мысли, с удовольствием выслушаю, как её сделать красивши) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 14:10 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Да, забыл, IntToText() осталась прежней, чисто асемблер, как и кидал ранее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 14:12 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
ИзопропилSiemarglИ добро пожаловать в волшебный мир SIMD. он не настолько волшебен, как иногда кажется. ускорь _ui64toa с помощью SSE4, а там и будем выводы делатьТы не понял идею. Нужно не одно число переводить, а пачку. Т.е. _ui64toa(const uint64_t val[4],.....) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 15:40 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
Siemargl, у интела в SIMD уже появилось деление 64 битных целых ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 15:56 |
|
||
|
IntToPChar на ASM для DELPHI
|
|||
|---|---|---|---|
|
#18+
ИзопропилSiemargl, у интела в SIMD уже появилось деление 64 битных целых ?Эмм, не нашел. Там простого деления я совсем не наблюдаю, только алгоритмами. Но оно не требуется. Нам нужно деление с остатком 64бит на 32бит. Оно реализуется 32-битными операциями, например так div_s64_rem() http://lxr.free-electrons.com/source/lib/div64.c ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2017, 22:04 |
|
||
|
|

start [/forum/topic.php?fid=16&msg=39380262&tid=1340523]: |
0ms |
get settings: |
8ms |
get forum list: |
11ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
138ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
| others: | 250ms |
| total: | 483ms |

| 0 / 0 |
