mkql_fold_ut.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. #include "mkql_computation_node_ut.h"
  2. #include <yql/essentials/minikql/mkql_node_cast.h>
  3. #include <yql/essentials/minikql/mkql_string_util.h>
  4. #include <yql/essentials/minikql/computation/mkql_computation_node_holders.h>
  5. #include <random>
  6. #include <ctime>
  7. #include <algorithm>
  8. namespace NKikimr {
  9. namespace NMiniKQL {
  10. Y_UNIT_TEST_SUITE(TMiniKQLFoldNodeTest) {
  11. Y_UNIT_TEST_LLVM(TestFoldOverList) {
  12. TSetup<LLVM> setup;
  13. TProgramBuilder& pb = *setup.PgmBuilder;
  14. auto data1 = pb.NewDataLiteral<ui32>(1);
  15. auto data2 = pb.NewDataLiteral<ui32>(2);
  16. auto data3 = pb.NewDataLiteral<ui32>(3);
  17. auto dataType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  18. auto list = pb.NewList(dataType, {data1, data2, data3});
  19. auto pgmReturn = pb.Fold(list, pb.NewDataLiteral<ui32>(0),
  20. [&](TRuntimeNode item, TRuntimeNode state) {
  21. return pb.Add(item, state);
  22. });
  23. auto graph = setup.BuildGraph(pgmReturn);
  24. auto res = graph->GetValue().template Get<ui32>();
  25. UNIT_ASSERT_VALUES_EQUAL(res, 6);
  26. }
  27. Y_UNIT_TEST_LLVM(TestFold1OverEmptyList) {
  28. TSetup<LLVM> setup;
  29. TProgramBuilder& pb = *setup.PgmBuilder;
  30. auto dataType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  31. auto list = pb.NewEmptyList(dataType);
  32. auto data2 = pb.NewDataLiteral<ui32>(2);
  33. auto pgmReturn = pb.Fold1(list, [&](TRuntimeNode item) {
  34. return pb.Mul(item, data2);
  35. },
  36. [&](TRuntimeNode item, TRuntimeNode state) {
  37. return pb.Add(item, state);
  38. });
  39. auto graph = setup.BuildGraph(pgmReturn);
  40. auto value = graph->GetValue();
  41. UNIT_ASSERT(!value);
  42. }
  43. Y_UNIT_TEST_LLVM(TestFold1OverSingleElementList) {
  44. TSetup<LLVM> setup;
  45. TProgramBuilder& pb = *setup.PgmBuilder;
  46. auto dataType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  47. auto data1 = pb.NewDataLiteral<ui32>(1);
  48. auto data2 = pb.NewDataLiteral<ui32>(2);
  49. auto list = pb.NewList(dataType, {data1});
  50. auto pgmReturn = pb.Fold1(list,
  51. [&](TRuntimeNode item) {
  52. return pb.Mul(item, data2);
  53. },
  54. [&](TRuntimeNode item, TRuntimeNode state) {
  55. return pb.Add(item, state);
  56. });
  57. auto graph = setup.BuildGraph(pgmReturn);
  58. auto value = graph->GetValue();
  59. UNIT_ASSERT(value);
  60. UNIT_ASSERT_VALUES_EQUAL(value.template Get<ui32>(), 2);
  61. }
  62. Y_UNIT_TEST_LLVM(TestFold1OverManyElementList) {
  63. TSetup<LLVM> setup;
  64. TProgramBuilder& pb = *setup.PgmBuilder;
  65. auto dataType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  66. auto data1 = pb.NewDataLiteral<ui32>(1);
  67. auto data2 = pb.NewDataLiteral<ui32>(2);
  68. auto list = pb.NewList(dataType, {data1, data2});
  69. auto pgmReturn = pb.Fold1(list,
  70. [&](TRuntimeNode item) {
  71. return pb.Mul(item, data2);
  72. },
  73. [&](TRuntimeNode item, TRuntimeNode state) {
  74. return pb.Add(item, state);
  75. });
  76. auto graph = setup.BuildGraph(pgmReturn);
  77. auto value = graph->GetValue();
  78. UNIT_ASSERT(value);
  79. UNIT_ASSERT_VALUES_EQUAL(value.template Get<ui32>(), 4);
  80. }
  81. Y_UNIT_TEST_LLVM(TestFoldWithAggrAdd) {
  82. TSetup<LLVM> setup;
  83. TProgramBuilder& pb = *setup.PgmBuilder;
  84. auto dataType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<float>::Id));
  85. auto data1 = pb.NewOptional(pb.NewDataLiteral<float>(1));
  86. auto data2 = pb.NewOptional(pb.NewDataLiteral<float>(2));
  87. auto data3 = pb.NewOptional(pb.NewDataLiteral<float>(3));
  88. auto data4 = pb.NewEmptyOptionalDataLiteral(NUdf::TDataType<float>::Id);
  89. auto data0 = pb.NewOptional(pb.NewDataLiteral<float>(42));
  90. auto list = pb.NewList(dataType, {data4, data3, data2, data1});
  91. auto pgmReturn = pb.Fold(list, data0,
  92. [&](TRuntimeNode item, TRuntimeNode state) {
  93. return pb.AggrAdd(pb.Increment(item), pb.Decrement(state));
  94. });
  95. auto graph = setup.BuildGraph(pgmReturn);
  96. auto res = graph->GetValue().template Get<float>();
  97. UNIT_ASSERT_VALUES_EQUAL(res, 47);
  98. }
  99. Y_UNIT_TEST_LLVM(TestNestedApply) {
  100. TSetup<LLVM> setup;
  101. TProgramBuilder& pb = *setup.PgmBuilder;
  102. auto data1 = pb.NewDataLiteral<i32>(1);
  103. auto data2 = pb.NewDataLiteral<i32>(2);
  104. auto data3 = pb.NewDataLiteral<i32>(3);
  105. auto dataType = pb.NewDataType(NUdf::TDataType<i32>::Id);
  106. auto list = pb.NewList(dataType, {data1, data2, data3});
  107. const auto callType = TCallableTypeBuilder(pb.GetTypeEnvironment(), "TEST", dataType).Add(dataType).Add(dataType).Build();
  108. auto pgmReturn = pb.Fold(list, pb.NewDataLiteral<i32>(100),
  109. [&](TRuntimeNode item, TRuntimeNode state) {
  110. return pb.Apply(pb.Callable(callType,
  111. [&](const TArrayRef<const TRuntimeNode>& args) {
  112. return pb.Sub(args[1], args[0]);
  113. }), {item, state});
  114. });
  115. auto graph = setup.BuildGraph(pgmReturn);
  116. auto res = graph->GetValue().template Get<i32>();
  117. UNIT_ASSERT_VALUES_EQUAL(res, 94);
  118. }
  119. Y_UNIT_TEST_LLVM(TestLogicalOpts) {
  120. TSetup<LLVM> setup;
  121. TProgramBuilder& pb = *setup.PgmBuilder;
  122. auto truth = pb.NewDataLiteral(true);
  123. auto falsehood = pb.NewDataLiteral(false);
  124. auto type = pb.NewDataType(NUdf::TDataType<bool>::Id);
  125. auto args = pb.NewList(type, {truth, falsehood});
  126. auto optTruth = pb.NewOptional(truth);
  127. auto optFalsehood = pb.NewOptional(falsehood);
  128. auto empty = pb.NewEmptyOptionalDataLiteral(NUdf::TDataType<bool>::Id);
  129. auto optType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<bool>::Id));
  130. auto opts = pb.NewList(optType, {empty, optTruth, optFalsehood});
  131. auto pgmReturn = pb.Fold(opts, pb.NewEmptyList(optType),
  132. [&](TRuntimeNode item, TRuntimeNode state) {
  133. const auto append = pb.Append(state, pb.Not(item));
  134. const auto one = pb.Fold(args, pb.NewEmptyList(optType),
  135. [&](TRuntimeNode item2, TRuntimeNode state2) {
  136. state2 = pb.Append(state2, pb.And({item, item2}));
  137. state2 = pb.Append(state2, pb.And({item2, item}));
  138. state2 = pb.Append(state2, pb.Or({item, item2}));
  139. state2 = pb.Append(state2, pb.Or({item2, item}));
  140. state2 = pb.Append(state2, pb.Xor({item, item2}));
  141. state2 = pb.Append(state2, pb.Xor({item2, item}));
  142. return state2;
  143. });
  144. const auto two = pb.Fold(opts, pb.NewEmptyList(optType),
  145. [&](TRuntimeNode item2, TRuntimeNode state2) {
  146. state2 = pb.Append(state2, pb.And({item, item2}));
  147. state2 = pb.Append(state2, pb.Or({item, item2}));
  148. state2 = pb.Append(state2, pb.Xor({item, item2}));
  149. return state2;
  150. });
  151. return pb.Extend({append, one, two});
  152. });
  153. auto graph = setup.BuildGraph(pgmReturn);
  154. auto res = graph->GetValue();
  155. UNIT_ASSERT_VALUES_EQUAL(res.GetListLength(), 66ULL);
  156. auto iterator = res.GetListIterator();
  157. NUdf::TUnboxedValue item;
  158. /// empty
  159. // not
  160. UNIT_ASSERT(iterator.Next(item));
  161. UNIT_ASSERT(!item);
  162. // and
  163. UNIT_ASSERT(iterator.Next(item));
  164. UNIT_ASSERT(!item);
  165. UNIT_ASSERT(iterator.Next(item));
  166. UNIT_ASSERT(!item);
  167. // or
  168. UNIT_ASSERT(iterator.Next(item));
  169. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  170. UNIT_ASSERT(iterator.Next(item));
  171. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  172. // xor
  173. UNIT_ASSERT(iterator.Next(item));
  174. UNIT_ASSERT(!item);
  175. UNIT_ASSERT(iterator.Next(item));
  176. UNIT_ASSERT(!item);
  177. // and
  178. UNIT_ASSERT(iterator.Next(item));
  179. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  180. UNIT_ASSERT(iterator.Next(item));
  181. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  182. // or
  183. UNIT_ASSERT(iterator.Next(item));
  184. UNIT_ASSERT(!item);
  185. UNIT_ASSERT(iterator.Next(item));
  186. UNIT_ASSERT(!item);
  187. // xor
  188. UNIT_ASSERT(iterator.Next(item));
  189. UNIT_ASSERT(!item);
  190. UNIT_ASSERT(iterator.Next(item));
  191. UNIT_ASSERT(!item);
  192. // and
  193. UNIT_ASSERT(iterator.Next(item));
  194. UNIT_ASSERT(!item);
  195. // or
  196. UNIT_ASSERT(iterator.Next(item));
  197. UNIT_ASSERT(!item);
  198. // xor
  199. UNIT_ASSERT(iterator.Next(item));
  200. UNIT_ASSERT(!item);
  201. // and
  202. UNIT_ASSERT(iterator.Next(item));
  203. UNIT_ASSERT(!item);
  204. // or
  205. UNIT_ASSERT(iterator.Next(item));
  206. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  207. // xor
  208. UNIT_ASSERT(iterator.Next(item));
  209. UNIT_ASSERT(!item);
  210. // and
  211. UNIT_ASSERT(iterator.Next(item));
  212. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  213. // or
  214. UNIT_ASSERT(iterator.Next(item));
  215. UNIT_ASSERT(!item);
  216. // xor
  217. UNIT_ASSERT(iterator.Next(item));
  218. UNIT_ASSERT(!item);
  219. /// true
  220. // not
  221. UNIT_ASSERT(iterator.Next(item));
  222. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  223. // and
  224. UNIT_ASSERT(iterator.Next(item));
  225. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  226. UNIT_ASSERT(iterator.Next(item));
  227. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  228. // or
  229. UNIT_ASSERT(iterator.Next(item));
  230. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  231. UNIT_ASSERT(iterator.Next(item));
  232. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  233. // xor
  234. UNIT_ASSERT(iterator.Next(item));
  235. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  236. UNIT_ASSERT(iterator.Next(item));
  237. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  238. // and
  239. UNIT_ASSERT(iterator.Next(item));
  240. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  241. UNIT_ASSERT(iterator.Next(item));
  242. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  243. // or
  244. UNIT_ASSERT(iterator.Next(item));
  245. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  246. UNIT_ASSERT(iterator.Next(item));
  247. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  248. // xor
  249. UNIT_ASSERT(iterator.Next(item));
  250. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  251. UNIT_ASSERT(iterator.Next(item));
  252. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  253. // and
  254. UNIT_ASSERT(iterator.Next(item));
  255. UNIT_ASSERT(!item);
  256. // or
  257. UNIT_ASSERT(iterator.Next(item));
  258. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  259. // xor
  260. UNIT_ASSERT(iterator.Next(item));
  261. UNIT_ASSERT(!item);
  262. // and
  263. UNIT_ASSERT(iterator.Next(item));
  264. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  265. // or
  266. UNIT_ASSERT(iterator.Next(item));
  267. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  268. // xor
  269. UNIT_ASSERT(iterator.Next(item));
  270. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  271. // and
  272. UNIT_ASSERT(iterator.Next(item));
  273. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  274. // or
  275. UNIT_ASSERT(iterator.Next(item));
  276. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  277. // xor
  278. UNIT_ASSERT(iterator.Next(item));
  279. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  280. /// false
  281. // not
  282. UNIT_ASSERT(iterator.Next(item));
  283. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  284. // and
  285. UNIT_ASSERT(iterator.Next(item));
  286. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  287. UNIT_ASSERT(iterator.Next(item));
  288. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  289. // or
  290. UNIT_ASSERT(iterator.Next(item));
  291. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  292. UNIT_ASSERT(iterator.Next(item));
  293. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  294. // xor
  295. UNIT_ASSERT(iterator.Next(item));
  296. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  297. UNIT_ASSERT(iterator.Next(item));
  298. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  299. // and
  300. UNIT_ASSERT(iterator.Next(item));
  301. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  302. UNIT_ASSERT(iterator.Next(item));
  303. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  304. // or
  305. UNIT_ASSERT(iterator.Next(item));
  306. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  307. UNIT_ASSERT(iterator.Next(item));
  308. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  309. // xor
  310. UNIT_ASSERT(iterator.Next(item));
  311. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  312. UNIT_ASSERT(iterator.Next(item));
  313. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  314. // and
  315. UNIT_ASSERT(iterator.Next(item));
  316. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  317. // or
  318. UNIT_ASSERT(iterator.Next(item));
  319. UNIT_ASSERT(!item);
  320. // xor
  321. UNIT_ASSERT(iterator.Next(item));
  322. UNIT_ASSERT(!item);
  323. // and
  324. UNIT_ASSERT(iterator.Next(item));
  325. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  326. // or
  327. UNIT_ASSERT(iterator.Next(item));
  328. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  329. // xor
  330. UNIT_ASSERT(iterator.Next(item));
  331. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  332. // and
  333. UNIT_ASSERT(iterator.Next(item));
  334. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  335. // or
  336. UNIT_ASSERT(iterator.Next(item));
  337. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  338. // xor
  339. UNIT_ASSERT(iterator.Next(item));
  340. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  341. UNIT_ASSERT(!iterator.Next(item));
  342. UNIT_ASSERT(!iterator.Next(item));
  343. }
  344. Y_UNIT_TEST_LLVM(TestFoldWithListInState) {
  345. TSetup<LLVM> setup;
  346. TProgramBuilder& pb = *setup.PgmBuilder;
  347. auto data1 = pb.NewDataLiteral<ui32>(1);
  348. auto data2 = pb.NewDataLiteral<ui32>(2);
  349. auto data3 = pb.NewDataLiteral<ui32>(3);
  350. auto dataType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  351. auto list = pb.NewList(dataType, {data1, data2, data3});
  352. auto optType = pb.NewOptionalType(dataType);
  353. auto empty = pb.AddMember(pb.AddMember(
  354. pb.NewEmptyStruct(), "Max", pb.NewEmptyOptional(optType)),
  355. "List", pb.NewEmptyList(dataType));
  356. auto pgmReturn = pb.Fold(list, empty,
  357. [&](TRuntimeNode item, TRuntimeNode state) {
  358. return pb.AddMember(pb.AddMember(pb.NewEmptyStruct(), "Max",
  359. pb.IfPresent({pb.Member(state, "Max")},
  360. [&](TRuntimeNode::TList oldMax) {
  361. return pb.NewOptional(pb.Max(oldMax.front(), item));
  362. }, pb.NewOptional(item))),
  363. "List", pb.Append(pb.Member(state, "List"), item)
  364. );
  365. });
  366. auto graph = setup.BuildGraph(pgmReturn);
  367. auto iterator = graph->GetValue().GetElement(0).GetListIterator();
  368. NUdf::TUnboxedValue item;
  369. UNIT_ASSERT(iterator.Next(item));
  370. UNIT_ASSERT_VALUES_EQUAL(item.template Get<ui32>(), 1);
  371. UNIT_ASSERT(iterator.Next(item));
  372. UNIT_ASSERT_VALUES_EQUAL(item.template Get<ui32>(), 2);
  373. UNIT_ASSERT(iterator.Next(item));
  374. UNIT_ASSERT_VALUES_EQUAL(item.template Get<ui32>(), 3);
  375. UNIT_ASSERT(!iterator.Next(item));
  376. UNIT_ASSERT(!iterator.Next(item));
  377. UNIT_ASSERT_VALUES_EQUAL(graph->GetValue().GetElement(1).template Get<ui32>(), 3);
  378. }
  379. Y_UNIT_TEST_LLVM(TestManyAppend) {
  380. TSetup<LLVM> setup;
  381. TProgramBuilder& pb = *setup.PgmBuilder;
  382. auto zeroList = pb.NewEmptyList(pb.NewDataType(NUdf::TDataType<ui32>::Id));
  383. zeroList = pb.Append(zeroList, pb.NewDataLiteral<ui32>(0));
  384. const ui32 n = 13;
  385. for (ui32 i = 0; i < n; ++i)
  386. zeroList = pb.Extend({zeroList, zeroList});
  387. auto state = pb.AddMember(pb.AddMember(pb.NewEmptyStruct(), "Counter",
  388. pb.NewDataLiteral<ui32>(0)), "NewList",
  389. pb.NewEmptyList(pb.NewDataType(NUdf::TDataType<ui32>::Id)));
  390. auto fold = pb.Fold(zeroList, state,
  391. [&](TRuntimeNode item, TRuntimeNode state) {
  392. Y_UNUSED(item);
  393. auto oldList = pb.Member(state, "NewList");
  394. auto oldCounter = pb.Member(state, "Counter");
  395. return pb.AddMember(pb.AddMember(pb.NewEmptyStruct(), "Counter",
  396. pb.Add(oldCounter, pb.NewDataLiteral<ui32>(1))),
  397. "NewList", pb.Append(oldList, oldCounter));
  398. });
  399. auto pgmReturn = pb.Member(fold, "NewList");
  400. auto graph = setup.BuildGraph(pgmReturn);
  401. UNIT_ASSERT_VALUES_EQUAL(graph->GetValue().GetListLength(), 1 << n);
  402. auto iterator = graph->GetValue().GetListIterator();
  403. ui32 i = 0;
  404. for (NUdf::TUnboxedValue item; iterator.Next(item); ++i) {
  405. UNIT_ASSERT_VALUES_EQUAL(i, item.template Get<ui32>());
  406. }
  407. UNIT_ASSERT(!iterator.Skip());
  408. UNIT_ASSERT_VALUES_EQUAL(i, 1 << n);
  409. }
  410. Y_UNIT_TEST_LLVM(TestManyPrepend) {
  411. TSetup<LLVM> setup;
  412. TProgramBuilder& pb = *setup.PgmBuilder;
  413. auto zeroList = pb.NewEmptyList(pb.NewDataType(NUdf::TDataType<ui32>::Id));
  414. zeroList = pb.Append(zeroList, pb.NewDataLiteral<ui32>(0));
  415. const ui32 n = 13;
  416. for (ui32 i = 0; i < n; ++i)
  417. zeroList = pb.Extend({zeroList, zeroList});
  418. auto state = pb.AddMember(pb.AddMember(pb.NewEmptyStruct(), "Counter",
  419. pb.NewDataLiteral<ui32>(0)), "NewList",
  420. pb.NewEmptyList(pb.NewDataType(NUdf::TDataType<ui32>::Id)));
  421. auto fold = pb.Fold(zeroList, state,
  422. [&](TRuntimeNode item, TRuntimeNode state) {
  423. Y_UNUSED(item);
  424. auto oldList = pb.Member(state, "NewList");
  425. auto oldCounter = pb.Member(state, "Counter");
  426. return pb.AddMember(pb.AddMember(pb.NewEmptyStruct(), "Counter",
  427. pb.Add(oldCounter, pb.NewDataLiteral<ui32>(1))),
  428. "NewList", pb.Prepend(oldCounter, oldList));
  429. });
  430. auto pgmReturn = pb.Member(fold, "NewList");
  431. auto graph = setup.BuildGraph(pgmReturn);
  432. UNIT_ASSERT_VALUES_EQUAL(graph->GetValue().GetListLength(), 1 << n);
  433. auto iterator = graph->GetValue().GetListIterator();
  434. ui32 i = 1 << n;
  435. for (NUdf::TUnboxedValue item; iterator.Next(item);) {
  436. UNIT_ASSERT_VALUES_EQUAL(--i, item.template Get<ui32>());
  437. }
  438. UNIT_ASSERT(!iterator.Skip());
  439. UNIT_ASSERT_VALUES_EQUAL(i, 0);
  440. }
  441. Y_UNIT_TEST_LLVM(TestManyExtend) {
  442. TSetup<LLVM> setup;
  443. TProgramBuilder& pb = *setup.PgmBuilder;
  444. auto zeroList = pb.NewEmptyList(pb.NewDataType(NUdf::TDataType<ui32>::Id));
  445. zeroList = pb.Append(zeroList, pb.NewDataLiteral<ui32>(0));
  446. const ui32 n = 13;
  447. for (ui32 i = 0; i < n; ++i)
  448. zeroList = pb.Extend({zeroList, zeroList});
  449. auto state = pb.AddMember(pb.AddMember(pb.NewEmptyStruct(), "Counter",
  450. pb.NewDataLiteral<ui32>(0)), "NewList",
  451. pb.NewEmptyList(pb.NewDataType(NUdf::TDataType<ui32>::Id)));
  452. auto fold = pb.Fold(zeroList, state,
  453. [&](TRuntimeNode item, TRuntimeNode state) {
  454. Y_UNUSED(item);
  455. auto oldList = pb.Member(state, "NewList");
  456. auto oldCounter = pb.Member(state, "Counter");
  457. auto oldCounterMul2 = pb.Mul(oldCounter, pb.NewDataLiteral<ui32>(2));
  458. auto extList = pb.NewEmptyList(pb.NewDataType(NUdf::TDataType<ui32>::Id));
  459. extList = pb.Append(extList, oldCounterMul2);
  460. extList = pb.Append(extList, pb.Increment(oldCounterMul2));
  461. return pb.AddMember(pb.AddMember(pb.NewEmptyStruct(), "Counter",
  462. pb.Add(oldCounter, pb.NewDataLiteral<ui32>(1))),
  463. "NewList", pb.Extend({oldList, extList}));
  464. });
  465. auto pgmReturn = pb.Member(fold, "NewList");
  466. auto graph = setup.BuildGraph(pgmReturn);
  467. UNIT_ASSERT_VALUES_EQUAL(graph->GetValue().GetListLength(), 1 << (n+1));
  468. auto iterator = graph->GetValue().GetListIterator();
  469. ui32 i = 0;
  470. for (NUdf::TUnboxedValue item; iterator.Next(item); ++i) {
  471. UNIT_ASSERT_VALUES_EQUAL(i, item.template Get<ui32>());
  472. }
  473. UNIT_ASSERT(!iterator.Skip());
  474. UNIT_ASSERT_VALUES_EQUAL(i, 1 << (n + 1));
  475. }
  476. Y_UNIT_TEST_LLVM(TestFoldSingular) {
  477. TSetup<LLVM> setup;
  478. TProgramBuilder& pb = *setup.PgmBuilder;
  479. auto data1 = pb.NewDataLiteral<ui32>(1);
  480. auto data2 = pb.NewDataLiteral<ui32>(2);
  481. auto data3 = pb.NewDataLiteral<ui32>(3);
  482. auto dataType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  483. auto list = pb.NewList(dataType, {data1, data2, data3});
  484. auto fold1 = pb.Fold(list, pb.NewDataLiteral<ui32>(0),
  485. [&](TRuntimeNode item, TRuntimeNode state) {
  486. Y_UNUSED(state);
  487. return item;
  488. });
  489. auto fold2 = pb.Fold(list, pb.NewDataLiteral<ui32>(0),
  490. [&](TRuntimeNode item, TRuntimeNode state) {
  491. Y_UNUSED(item);
  492. return state;
  493. });
  494. auto pgmReturn = pb.NewList(dataType, {fold1, fold2});
  495. auto graph = setup.BuildGraph(pgmReturn);
  496. auto iterator = graph->GetValue().GetListIterator();
  497. NUdf::TUnboxedValue item;
  498. UNIT_ASSERT(iterator.Next(item));
  499. UNIT_ASSERT_VALUES_EQUAL(item.template Get<ui32>(), 3);
  500. UNIT_ASSERT(iterator.Next(item));
  501. UNIT_ASSERT_VALUES_EQUAL(item.template Get<ui32>(), 0);
  502. UNIT_ASSERT(!iterator.Next(item));
  503. UNIT_ASSERT(!iterator.Next(item));
  504. }
  505. Y_UNIT_TEST_LLVM(TestSumListSizes) {
  506. TSetup<LLVM> setup;
  507. TProgramBuilder& pb = *setup.PgmBuilder;
  508. auto itemType = pb.NewDataType(NUdf::TDataType<float>::Id);
  509. auto item = pb.NewDataLiteral<float>(0.f);
  510. auto listType = pb.NewListType(itemType);
  511. auto data0 = pb.NewEmptyList(itemType);
  512. auto data1 = pb.NewList(itemType, {item});
  513. auto data2 = pb.NewList(itemType, {item, item, item});
  514. auto data3 = pb.NewList(itemType, {item, item, item, item, item});
  515. auto list = pb.NewList(listType, {data0, data1, data2, data3});
  516. auto pgmReturn = pb.Fold1(list,
  517. [&](TRuntimeNode item) { return pb.Length(item); },
  518. [&](TRuntimeNode item, TRuntimeNode state) { return pb.AggrAdd(state, pb.Length(item)); }
  519. );
  520. auto graph = setup.BuildGraph(pgmReturn);
  521. UNIT_ASSERT_VALUES_EQUAL(9ULL, graph->GetValue().template Get<ui64>());
  522. }
  523. Y_UNIT_TEST_LLVM(TestHasListsItems) {
  524. TSetup<LLVM> setup;
  525. TProgramBuilder& pb = *setup.PgmBuilder;
  526. auto itemType = pb.NewDataType(NUdf::TDataType<float>::Id);
  527. auto item = pb.NewDataLiteral<float>(0.f);
  528. auto listType = pb.NewListType(itemType);
  529. auto data0 = pb.NewEmptyList(itemType);
  530. auto data1 = pb.NewList(itemType, {item});
  531. auto data2 = pb.NewEmptyList(itemType);
  532. auto list = pb.NewList(listType, {data0, data1, data2});
  533. auto pgmReturn = pb.Fold(list, pb.NewOptional(pb.NewDataLiteral<bool>(false)),
  534. [&](TRuntimeNode item, TRuntimeNode state) { return pb.Or({state, pb.HasItems(item)}); }
  535. );
  536. auto graph = setup.BuildGraph(pgmReturn);
  537. UNIT_ASSERT(graph->GetValue().template Get<bool>());
  538. }
  539. Y_UNIT_TEST_LLVM(TestConcat) {
  540. TSetup<LLVM> setup;
  541. TProgramBuilder& pb = *setup.PgmBuilder;
  542. auto data0 = pb.NewDataLiteral<NUdf::EDataSlot::String>("X");
  543. auto data1 = pb.NewDataLiteral<NUdf::EDataSlot::String>("aa");
  544. auto data2 = pb.NewDataLiteral<NUdf::EDataSlot::String>("bbb");
  545. auto data3 = pb.NewDataLiteral<NUdf::EDataSlot::String>("zzzz");
  546. auto type = pb.NewDataType(NUdf::EDataSlot::String);
  547. auto list = pb.NewList(type, {data1, data2, data3});
  548. auto pgmReturn = pb.Fold(list, data0,
  549. [&](TRuntimeNode item, TRuntimeNode state) {
  550. return pb.Concat(state, item);
  551. });
  552. auto graph = setup.BuildGraph(pgmReturn);
  553. auto res = graph->GetValue();
  554. UNBOXED_VALUE_STR_EQUAL(res, "Xaabbbzzzz");
  555. }
  556. Y_UNIT_TEST_LLVM(TestConcatOpt) {
  557. TSetup<LLVM> setup;
  558. TProgramBuilder& pb = *setup.PgmBuilder;
  559. auto data0 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::String>(""));
  560. auto data1 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::String>("very large string"));
  561. auto data2 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::String>(" + "));
  562. auto data3 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::String>("small"));
  563. auto type = pb.NewOptionalType(pb.NewDataType(NUdf::EDataSlot::String));
  564. auto list = pb.NewList(type, {data1, data2, data3, data0});
  565. auto pgmReturn = pb.Fold(list, data0,
  566. [&](TRuntimeNode item, TRuntimeNode state) {
  567. return pb.Concat(state, item);
  568. });
  569. auto graph = setup.BuildGraph(pgmReturn);
  570. auto res = graph->GetValue();
  571. UNBOXED_VALUE_STR_EQUAL(res, "very large string + small");
  572. }
  573. Y_UNIT_TEST_LLVM(TestAggrConcat) {
  574. TSetup<LLVM> setup;
  575. TProgramBuilder& pb = *setup.PgmBuilder;
  576. const auto type = pb.NewOptionalType(pb.NewDataType(NUdf::EDataSlot::Utf8));
  577. const auto data0 = pb.NewEmptyOptional(type);
  578. const auto data1 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("PREFIX:"));
  579. const auto data2 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("very large string"));
  580. const auto data3 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>(":SUFFIX"));
  581. const auto list = pb.NewList(type, {data0, data1, data0, data2, data3, data0});
  582. const auto pgmReturn = pb.Fold1(list,
  583. [&](TRuntimeNode item) { return item; },
  584. [&](TRuntimeNode item, TRuntimeNode state) { return pb.AggrConcat(state, item); }
  585. );
  586. const auto graph = setup.BuildGraph(pgmReturn);
  587. const auto str = graph->GetValue();
  588. UNBOXED_VALUE_STR_EQUAL(str, "PREFIX:very large string:SUFFIX");
  589. }
  590. Y_UNIT_TEST_LLVM(TestLongFold) {
  591. for (ui32 i = 0; i < 10; ++i) {
  592. TSetup<LLVM> setup;
  593. TProgramBuilder& pb = *setup.PgmBuilder;
  594. const ui32 n = 1000;
  595. auto firstList = pb.Replicate(pb.NewDataLiteral<ui32>(0),
  596. pb.NewDataLiteral<ui64>(n), "", 0, 0);
  597. auto secondList = pb.Replicate(firstList, pb.NewDataLiteral<ui64>(n), "", 0, 0);
  598. auto pgmReturn = pb.Fold(secondList, pb.NewDataLiteral<ui32>(0),
  599. [&](TRuntimeNode item, TRuntimeNode state) {
  600. auto partialSum = pb.Fold(item, pb.NewDataLiteral<ui32>(0),
  601. [&](TRuntimeNode item, TRuntimeNode state) {
  602. Y_UNUSED(item);
  603. return pb.AggrAdd(state, pb.NewDataLiteral<ui32>(1));
  604. });
  605. return pb.AggrAdd(state, partialSum);
  606. });
  607. auto graph = setup.BuildGraph(pgmReturn);
  608. auto value = graph->GetValue().template Get<ui32>();
  609. UNIT_ASSERT_VALUES_EQUAL(value, n * n);
  610. }
  611. }
  612. Y_UNIT_TEST_LLVM(TestFoldAggrAddIntervals) {
  613. TSetup<LLVM> setup;
  614. TProgramBuilder& pb = *setup.PgmBuilder;
  615. const auto upper = i64(+1000LL);
  616. const auto lower = i64(-1000LL);
  617. const auto part = i64(100LL);
  618. const auto from = pb.NewDataLiteral<NUdf::EDataSlot::Interval>(NUdf::TStringRef((const char*)&lower, sizeof(lower)));
  619. const auto stop = pb.NewDataLiteral<NUdf::EDataSlot::Interval>(NUdf::TStringRef((const char*)&upper, sizeof(upper)));
  620. const auto step = pb.NewDataLiteral<NUdf::EDataSlot::Interval>(NUdf::TStringRef((const char*)&part, sizeof(part)));
  621. const auto list = pb.ListFromRange(from, stop, step);
  622. const auto pgmReturn = pb.Fold1(pb.ListFromRange(from, stop, step),
  623. [&](TRuntimeNode item) { return pb.NewOptional(item); },
  624. [&](TRuntimeNode item, TRuntimeNode state) { return pb.AggrAdd(pb.NewOptional(item), state); }
  625. );
  626. const auto graph = setup.BuildGraph(pgmReturn);
  627. const auto value = graph->GetValue();
  628. UNIT_ASSERT_VALUES_EQUAL(value.template Get<i64>(), -1000LL);
  629. }
  630. Y_UNIT_TEST_LLVM(TestFoldFoldPerf) {
  631. TSetup<LLVM> setup;
  632. TProgramBuilder& pb = *setup.PgmBuilder;
  633. const ui32 n = 3333U;
  634. const auto firstList = pb.Replicate(pb.NewDataLiteral<ui32>(1), pb.NewDataLiteral<ui64>(n), "", 0, 0);
  635. const auto secondList = pb.Replicate(firstList, pb.NewDataLiteral<ui64>(n), "", 0, 0);
  636. const auto pgmReturn = pb.Fold(secondList, pb.NewDataLiteral<ui32>(0),
  637. [&](TRuntimeNode item, TRuntimeNode state) {
  638. const auto partialSum = pb.Fold(item, pb.NewDataLiteral<ui32>(0),
  639. [&](TRuntimeNode i2, TRuntimeNode state) {
  640. return pb.AggrAdd(state, i2);
  641. });
  642. return pb.AggrAdd(state, partialSum);
  643. });
  644. const auto t1 = TInstant::Now();
  645. const auto graph = setup.BuildGraph(pgmReturn);
  646. const auto t2 = TInstant::Now();
  647. const auto value = graph->GetValue().template Get<ui32>();
  648. const auto t3 = TInstant::Now();
  649. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ")." << Endl;
  650. UNIT_ASSERT_VALUES_EQUAL(value, n * n);
  651. }
  652. std::vector<double> MakeSamples() {
  653. std::default_random_engine eng;
  654. std::uniform_real_distribution<double> unif(-999.0, +999.0);
  655. std::vector<double> samples(3333333U);
  656. eng.seed(std::time(nullptr));
  657. std::generate(samples.begin(), samples.end(), std::bind(std::move(unif), std::move(eng)));
  658. return samples;
  659. }
  660. static const auto Samples = MakeSamples();
  661. Y_UNIT_TEST_LLVM(TestSumDoubleArrayListPerf) {
  662. TSetup<LLVM> setup;
  663. const auto t = TInstant::Now();
  664. const double sum = std::accumulate(Samples.cbegin(), Samples.cend(), 0.0);
  665. const auto cppTime = TInstant::Now() - t;
  666. TProgramBuilder& pb = *setup.PgmBuilder;
  667. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  668. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  669. const auto pgmReturn = pb.Fold1(pb.Collect(TRuntimeNode(list, false)),
  670. [&](TRuntimeNode item) { return item; },
  671. [&](TRuntimeNode item, TRuntimeNode state) { return pb.AggrAdd(state, item); }
  672. );
  673. const auto t1 = TInstant::Now();
  674. const auto graph = setup.BuildGraph(pgmReturn, {list});
  675. NUdf::TUnboxedValue* items = nullptr;
  676. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  677. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  678. const auto t2 = TInstant::Now();
  679. const auto& value = graph->GetValue();
  680. const auto t3 = TInstant::Now();
  681. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  682. UNIT_ASSERT_VALUES_EQUAL(value.template Get<double>(), sum);
  683. }
  684. Y_UNIT_TEST_LLVM(TestSumDoubleLazyListPerf) {
  685. TSetup<LLVM> setup;
  686. const auto t = TInstant::Now();
  687. const double sum = std::accumulate(Samples.cbegin(), Samples.cend(), 0.0);
  688. const auto cppTime = TInstant::Now() - t;
  689. TProgramBuilder& pb = *setup.PgmBuilder;
  690. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  691. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  692. const auto pgmReturn = pb.Fold1(pb.LazyList(TRuntimeNode(list, false)),
  693. [&](TRuntimeNode item) { return item; },
  694. [&](TRuntimeNode item, TRuntimeNode state) { return pb.AggrAdd(state, item); }
  695. );
  696. const auto t1 = TInstant::Now();
  697. const auto graph = setup.BuildGraph(pgmReturn, {list});
  698. NUdf::TUnboxedValue* items = nullptr;
  699. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  700. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  701. const auto t2 = TInstant::Now();
  702. const auto& value = graph->GetValue();
  703. const auto t3 = TInstant::Now();
  704. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  705. UNIT_ASSERT_VALUES_EQUAL(value.template Get<double>(), sum);
  706. }
  707. Y_UNIT_TEST_LLVM(TestSumDoubleFilteredArrayListPerf) {
  708. TSetup<LLVM> setup;
  709. const auto t = TInstant::Now();
  710. const double sum = std::accumulate(Samples.cbegin(), Samples.cend(), 0.0, [](double s, double v) { return v > 0.0 ? s + v : s; });
  711. const auto cppTime = TInstant::Now() - t;
  712. TProgramBuilder& pb = *setup.PgmBuilder;
  713. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  714. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  715. const auto pgmReturn = pb.Fold1(
  716. pb.Filter(pb.Collect(TRuntimeNode(list, false)),
  717. [&](TRuntimeNode item) { return pb.AggrGreater(item, pb.NewDataLiteral(0.0)); }
  718. ),
  719. [&](TRuntimeNode item) { return item; },
  720. [&](TRuntimeNode item, TRuntimeNode state) { return pb.AggrAdd(state, item); }
  721. );
  722. const auto t1 = TInstant::Now();
  723. const auto graph = setup.BuildGraph(pgmReturn, {list});
  724. NUdf::TUnboxedValue* items = nullptr;
  725. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  726. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  727. const auto t2 = TInstant::Now();
  728. const auto& value = graph->GetValue();
  729. const auto t3 = TInstant::Now();
  730. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  731. UNIT_ASSERT_VALUES_EQUAL(value.template Get<double>(), sum);
  732. }
  733. Y_UNIT_TEST_LLVM(TestSumDoubleFilteredLazyListPerf) {
  734. TSetup<LLVM> setup;
  735. const auto t = TInstant::Now();
  736. const double sum = std::accumulate(Samples.cbegin(), Samples.cend(), 0.0, [](double s, double v) { return v > 0.0 ? s + v : s; });
  737. const auto cppTime = TInstant::Now() - t;
  738. TProgramBuilder& pb = *setup.PgmBuilder;
  739. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  740. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  741. const auto pgmReturn = pb.Fold1(
  742. pb.Filter(pb.LazyList(TRuntimeNode(list, false)),
  743. [&](TRuntimeNode item) { return pb.AggrGreater(item, pb.NewDataLiteral(0.0)); }
  744. ),
  745. [&](TRuntimeNode item) { return item; },
  746. [&](TRuntimeNode item, TRuntimeNode state) { return pb.AggrAdd(state, item); }
  747. );
  748. const auto t1 = TInstant::Now();
  749. const auto graph = setup.BuildGraph(pgmReturn, {list});
  750. NUdf::TUnboxedValue* items = nullptr;
  751. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  752. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  753. const auto t2 = TInstant::Now();
  754. const auto& value = graph->GetValue();
  755. const auto t3 = TInstant::Now();
  756. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  757. UNIT_ASSERT_VALUES_EQUAL(value.template Get<double>(), sum);
  758. }
  759. Y_UNIT_TEST_LLVM(TestMinMaxSumDoubleArrayListPerf) {
  760. TSetup<LLVM> setup;
  761. double min(Samples.front()), max(Samples.front()), sum(0.0);
  762. const auto t = TInstant::Now();
  763. for (const auto v : Samples) {
  764. min = std::fmin(min, v);
  765. max = std::fmax(max, v);
  766. sum += v;
  767. }
  768. const auto cppTime = TInstant::Now() - t;
  769. TProgramBuilder& pb = *setup.PgmBuilder;
  770. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  771. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  772. const auto pgmReturn = pb.Fold1(pb.Collect(TRuntimeNode(list, false)),
  773. [&](TRuntimeNode item) { return pb.NewTuple({item, item, item}); },
  774. [&](TRuntimeNode item, TRuntimeNode state) {
  775. return pb.NewTuple({pb.AggrMin(pb.Nth(state, 0U), item), pb.AggrMax(pb.Nth(state, 1U), item), pb.AggrAdd(pb.Nth(state, 2U), item)});
  776. });
  777. const auto t1 = TInstant::Now();
  778. const auto graph = setup.BuildGraph(pgmReturn, {list});
  779. NUdf::TUnboxedValue* items = nullptr;
  780. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  781. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  782. const auto t2 = TInstant::Now();
  783. const auto& value = graph->GetValue();
  784. const auto t3 = TInstant::Now();
  785. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  786. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(0U).template Get<double>(), min);
  787. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(1U).template Get<double>(), max);
  788. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(2U).template Get<double>(), sum);
  789. }
  790. Y_UNIT_TEST_LLVM(TestMinMaxSumDoubleLazyListPerf) {
  791. TSetup<LLVM> setup;
  792. double min(Samples.front()), max(Samples.front()), sum(0.0);
  793. const auto t = TInstant::Now();
  794. for (const auto v : Samples) {
  795. min = std::fmin(min, v);
  796. max = std::fmax(max, v);
  797. sum += v;
  798. }
  799. const auto cppTime = TInstant::Now() - t;
  800. TProgramBuilder& pb = *setup.PgmBuilder;
  801. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  802. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  803. const auto pgmReturn = pb.Fold1(pb.LazyList(TRuntimeNode(list, false)),
  804. [&](TRuntimeNode item) { return pb.NewTuple({item, item, item}); },
  805. [&](TRuntimeNode item, TRuntimeNode state) {
  806. return pb.NewTuple({pb.AggrMin(pb.Nth(state, 0U), item), pb.AggrMax(pb.Nth(state, 1U), item), pb.AggrAdd(pb.Nth(state, 2U), item)});
  807. });
  808. const auto t1 = TInstant::Now();
  809. const auto graph = setup.BuildGraph(pgmReturn, {list});
  810. NUdf::TUnboxedValue* items = nullptr;
  811. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  812. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  813. const auto t2 = TInstant::Now();
  814. const auto& value = graph->GetValue();
  815. const auto t3 = TInstant::Now();
  816. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  817. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(0U).template Get<double>(), min);
  818. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(1U).template Get<double>(), max);
  819. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(2U).template Get<double>(), sum);
  820. }
  821. Y_UNIT_TEST_LLVM(TestMinMaxSumDoubleFilteredArrayListPerf) {
  822. TSetup<LLVM> setup;
  823. double min(std::nan("")), max(std::nan("")), sum(0.0);
  824. const auto t = TInstant::Now();
  825. for (const auto v : Samples) {
  826. if (v < 0.0) {
  827. min = std::fmin(min, v);
  828. max = std::fmax(max, v);
  829. sum += v;
  830. }
  831. }
  832. const auto cppTime = TInstant::Now() - t;
  833. TProgramBuilder& pb = *setup.PgmBuilder;
  834. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  835. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  836. const auto pgmReturn = pb.Fold1(
  837. pb.Filter(pb.Collect(TRuntimeNode(list, false)),
  838. [&](TRuntimeNode item) { return pb.AggrLess(item, pb.NewDataLiteral(0.0)); }
  839. ),
  840. [&](TRuntimeNode item) { return pb.NewTuple({item, item, item}); },
  841. [&](TRuntimeNode item, TRuntimeNode state) {
  842. return pb.NewTuple({pb.AggrMin(pb.Nth(state, 0U), item), pb.AggrMax(pb.Nth(state, 1U), item), pb.AggrAdd(pb.Nth(state, 2U), item)});
  843. });
  844. const auto t1 = TInstant::Now();
  845. const auto graph = setup.BuildGraph(pgmReturn, {list});
  846. NUdf::TUnboxedValue* items = nullptr;
  847. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  848. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  849. const auto t2 = TInstant::Now();
  850. const auto& value = graph->GetValue();
  851. const auto t3 = TInstant::Now();
  852. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  853. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(0U).template Get<double>(), min);
  854. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(1U).template Get<double>(), max);
  855. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(2U).template Get<double>(), sum);
  856. }
  857. Y_UNIT_TEST_LLVM(TestMinMaxSumDoubleFilteredLazyListPerf) {
  858. TSetup<LLVM> setup;
  859. double min(std::nan("")), max(std::nan("")), sum(0.0);
  860. const auto t = TInstant::Now();
  861. for (const auto v : Samples) {
  862. if (v < 0.0) {
  863. min = std::fmin(min, v);
  864. max = std::fmax(max, v);
  865. sum += v;
  866. }
  867. }
  868. const auto cppTime = TInstant::Now() - t;
  869. TProgramBuilder& pb = *setup.PgmBuilder;
  870. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  871. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  872. const auto pgmReturn = pb.Fold1(
  873. pb.Filter(pb.LazyList(TRuntimeNode(list, false)),
  874. [&](TRuntimeNode item) { return pb.AggrLess(item, pb.NewDataLiteral(0.0)); }
  875. ),
  876. [&](TRuntimeNode item) { return pb.NewTuple({item, item, item}); },
  877. [&](TRuntimeNode item, TRuntimeNode state) {
  878. return pb.NewTuple({pb.AggrMin(pb.Nth(state, 0U), item), pb.AggrMax(pb.Nth(state, 1U), item), pb.AggrAdd(pb.Nth(state, 2U), item)});
  879. });
  880. const auto t1 = TInstant::Now();
  881. const auto graph = setup.BuildGraph(pgmReturn, {list});
  882. NUdf::TUnboxedValue* items = nullptr;
  883. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  884. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  885. const auto t2 = TInstant::Now();
  886. const auto& value = graph->GetValue();
  887. const auto t3 = TInstant::Now();
  888. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  889. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(0U).template Get<double>(), min);
  890. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(1U).template Get<double>(), max);
  891. UNIT_ASSERT_VALUES_EQUAL(value.GetElement(2U).template Get<double>(), sum);
  892. }
  893. Y_UNIT_TEST_LLVM(TestAvgDoubleByTupleFoldArrayListPerf) {
  894. TSetup<LLVM> setup;
  895. const auto t = TInstant::Now();
  896. const double avg = std::accumulate(Samples.cbegin(), Samples.cend(), 0.0) / Samples.size();
  897. const auto cppTime = TInstant::Now() - t;
  898. TProgramBuilder& pb = *setup.PgmBuilder;
  899. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  900. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  901. const auto fold = pb.Fold(pb.Collect(TRuntimeNode(list, false)),
  902. pb.NewTuple({pb.NewDataLiteral(0.0), pb.NewDataLiteral<ui64>(0ULL)}),
  903. [&](TRuntimeNode item, TRuntimeNode state) {
  904. return pb.NewTuple({pb.AggrAdd(pb.Nth(state, 0), item), pb.Increment(pb.Nth(state, 1))});
  905. });
  906. const auto pgmReturn = pb.Div(pb.Nth(fold, 0U), pb.Nth(fold, 1U));
  907. const auto t1 = TInstant::Now();
  908. const auto graph = setup.BuildGraph(pgmReturn, {list});
  909. NUdf::TUnboxedValue* items = nullptr;
  910. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  911. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  912. const auto t2 = TInstant::Now();
  913. const auto& value = graph->GetValue();
  914. const auto t3 = TInstant::Now();
  915. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  916. UNIT_ASSERT_VALUES_EQUAL(value.template Get<double>(), avg);
  917. }
  918. Y_UNIT_TEST_LLVM(TestAvgDoubleByTupleFoldLazyListPerf) {
  919. TSetup<LLVM> setup;
  920. const auto t = TInstant::Now();
  921. const double avg = std::accumulate(Samples.cbegin(), Samples.cend(), 0.0) / Samples.size();
  922. const auto cppTime = TInstant::Now() - t;
  923. TProgramBuilder& pb = *setup.PgmBuilder;
  924. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  925. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  926. const auto fold = pb.Fold(pb.LazyList(TRuntimeNode(list, false)),
  927. pb.NewTuple({pb.NewDataLiteral(0.0), pb.NewDataLiteral<ui64>(0ULL)}),
  928. [&](TRuntimeNode item, TRuntimeNode state) {
  929. return pb.NewTuple({pb.AggrAdd(pb.Nth(state, 0U), item), pb.Increment(pb.Nth(state, 1U))});
  930. });
  931. const auto pgmReturn = pb.Div(pb.Nth(fold, 0U), pb.Nth(fold, 1U));
  932. const auto t1 = TInstant::Now();
  933. const auto graph = setup.BuildGraph(pgmReturn, {list});
  934. NUdf::TUnboxedValue* items = nullptr;
  935. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  936. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  937. const auto t2 = TInstant::Now();
  938. const auto& value = graph->GetValue();
  939. const auto t3 = TInstant::Now();
  940. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  941. UNIT_ASSERT_VALUES_EQUAL(value.template Get<double>(), avg);
  942. }
  943. Y_UNIT_TEST_LLVM(TestAvgDoubleByCollectFoldLazyListPerf) {
  944. TSetup<LLVM> setup;
  945. const auto t = TInstant::Now();
  946. const double avg = std::accumulate(Samples.cbegin(), Samples.cend(), 0.0) / Samples.size();
  947. const auto cppTime = TInstant::Now() - t;
  948. TProgramBuilder& pb = *setup.PgmBuilder;
  949. const auto listType = pb.NewListType(pb.NewDataType(NUdf::TDataType<double>::Id));
  950. const auto list = TCallableBuilder(pb.GetTypeEnvironment(), "TestList", listType).Build();
  951. const auto src = pb.Collect(pb.LazyList(TRuntimeNode(list, false)));
  952. const auto pgmReturn = pb.Div(
  953. pb.Fold(src, pb.NewDataLiteral(0.0),
  954. [&](TRuntimeNode item, TRuntimeNode state) { return pb.AggrAdd(state, item); }
  955. ),
  956. pb.Length(src)
  957. );
  958. const auto t1 = TInstant::Now();
  959. const auto graph = setup.BuildGraph(pgmReturn, {list});
  960. NUdf::TUnboxedValue* items = nullptr;
  961. graph->GetEntryPoint(0, true)->SetValue(graph->GetContext(), graph->GetHolderFactory().CreateDirectArrayHolder(Samples.size(), items));
  962. std::transform(Samples.cbegin(), Samples.cend(), items, &ToValue<double>);
  963. const auto t2 = TInstant::Now();
  964. const auto& value = graph->GetValue();
  965. const auto t3 = TInstant::Now();
  966. Cerr << "Time is " << t3 - t1 << " (" << t2 - t1 << " + " << t3 - t2 << ") vs C++ " << cppTime << Endl;
  967. UNIT_ASSERT_VALUES_EQUAL(value.template Get<double>(), avg);
  968. }
  969. }
  970. }
  971. }