From e6d58121f1a38afb201f349cea5005a42e389907 Mon Sep 17 00:00:00 2001 From: lucasdelimanogueira Date: Wed, 5 Jun 2024 20:24:09 -0300 Subject: [PATCH] fix memory usage --- build/cuda.cu.o | Bin 220904 -> 220624 bytes build/tensor.o | Bin 55304 -> 48712 bytes mprofile_20240605162109.dat | 28 + mprofile_20240605162319.dat | 257 +++++ norch/__pycache__/tensor.cpython-38.pyc | Bin 20819 -> 20982 bytes norch/csrc/cuda.cu | 10 +- norch/csrc/tensor.cpp | 880 +++++++----------- norch/csrc/tensor.h | 2 + norch/libtensor.so | Bin 401384 -> 397264 bytes norch/nn/__pycache__/loss.cpython-38.pyc | Bin 2874 -> 2874 bytes norch/nn/loss.py | 2 +- .../optimizers/__pycache__/sgd.cpython-38.pyc | Bin 1274 -> 1274 bytes norch/optim/optimizers/sgd.py | 1 + norch/tensor.py | 36 +- profiling_results.prof | Bin 0 -> 46211 bytes train_singlegpu.py | 97 ++ 16 files changed, 754 insertions(+), 559 deletions(-) create mode 100644 mprofile_20240605162109.dat create mode 100644 mprofile_20240605162319.dat create mode 100644 profiling_results.prof create mode 100644 train_singlegpu.py diff --git a/build/cuda.cu.o b/build/cuda.cu.o index 437afebaa62eae8c802353ad66e6ca4694b15154..21f4bd171ff68a8ace583f98a279203f8124ba21 100644 GIT binary patch delta 22929 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
  • S+1kG?x)tbzB$yq*7ea#3kf0*7bt!-qc-%O6^bZQ&r5iuyO}dm!~S|l}Z~J{!{bS5{&}+jX!sd zS2G8Oi|9X(RFHRb^F+x*;=waIO8qu4d|~L2t5Pz4+JqG#Y$#2fX79XfeXc#?=p^Upcb)38DDlwb7r7DBF zjjA|1oD~0jx{kO`71GNl&&d`t75|d1_GE`UC7XwER#|rX)%hF>cE5_`gp)$2d#OP= zm_SR3Pq~BMn8ykC`${0r8Q&jOV+6Q~oN_v%So-%pZa-OCt z*leCD*^EykYDQISm7E*yoMIj!Io2{C9j0!`rA5zCrMZ;ruWB24C!6O%p0d2tRVACv z;~%@#i_O(f^&C!SdfKDk7F*^URSB8ho~mp(rMgqS$5(^GL;x39+FUtH=m4nNuI*IF&exoU>K?Q5;%+`Zc3rtn=|()a+3dy1&}Y-t*K8GV+)Y&_)ZI5OTvxp@F5DwDaexYq4_{Ny ld0AI?rimIfKHNS2Ooe{ERIMCO#rGJc&%I`@8k8Sy{r`jpP2m6l delta 22536 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 DJrR9H diff --git a/build/tensor.o b/build/tensor.o index 7b38f1968ab8a8c8b86a798a75b9e79aa73444be..d3962d93c4303a2a34caaf30903a53755186a69e 100644 GIT binary patch literal 48712 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 Z?cGng@f%GQUfWl0cemhkcr14O|1X;%6!ZW9 literal 55304 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 avcLB#JJv^0LD2qrySzOTx}!YW@&CUWmqjK3 diff --git a/mprofile_20240605162109.dat b/mprofile_20240605162109.dat new file mode 100644 index 0000000..5e8562a --- /dev/null +++ b/mprofile_20240605162109.dat @@ -0,0 +1,28 @@ +CMDLINE /usr/bin/python3 train_singlegpu.py +MEM 1.109375 1717615269.6916 +MEM 14.167969 1717615269.7921 +MEM 21.085938 1717615269.8925 +MEM 26.617188 1717615269.9930 +MEM 32.312500 1717615270.0934 +MEM 38.429688 1717615270.1939 +MEM 40.683594 1717615270.2943 +MEM 46.445312 1717615270.3947 +MEM 54.089844 1717615270.4953 +MEM 58.347656 1717615270.5959 +MEM 63.308594 1717615270.6964 +MEM 65.226562 1717615270.7970 +MEM 70.898438 1717615270.8975 +MEM 76.828125 1717615270.9980 +MEM 82.242188 1717615271.0986 +MEM 87.656250 1717615271.1991 +MEM 93.328125 1717615271.2996 +MEM 98.742188 1717615271.4001 +MEM 104.671875 1717615271.5006 +MEM 135.867188 1717615271.6011 +MEM 117.457031 1717615271.7016 +MEM 125.246094 1717615271.8022 +MEM 125.503906 1717615271.9026 +MEM 125.503906 1717615272.0029 +MEM 127.074219 1717615272.1032 +MEM 127.074219 1717615272.2036 +MEM 73.593750 1717615272.3040 diff --git a/mprofile_20240605162319.dat b/mprofile_20240605162319.dat new file mode 100644 index 0000000..b859d5e --- /dev/null +++ b/mprofile_20240605162319.dat @@ -0,0 +1,257 @@ +CMDLINE /usr/bin/python3 train_singlegpu.py +MEM 1.171875 1717615399.9716 +MEM 18.777344 1717615400.0720 +MEM 25.433594 1717615400.1725 +MEM 30.570312 1717615400.2729 +MEM 36.207031 1717615400.3734 +MEM 40.167969 1717615400.4738 +MEM 46.121094 1717615400.5743 +MEM 56.503906 1717615400.6747 +MEM 63.429688 1717615400.7751 +MEM 70.007812 1717615400.8755 +MEM 84.187500 1717615400.9758 +MEM 98.109375 1717615401.0761 +MEM 140.132812 1717615401.1765 +MEM 125.375000 1717615401.2769 +MEM 125.632812 1717615401.3772 +MEM 126.433594 1717615401.4775 +MEM 127.203125 1717615401.5778 +MEM 127.203125 1717615401.6781 +MEM 127.316406 1717615401.7785 +MEM 127.316406 1717615401.8787 +MEM 134.515625 1717615401.9790 +MEM 134.773438 1717615402.0793 +MEM 136.054688 1717615402.1796 +MEM 140.953125 1717615402.2799 +MEM 140.953125 1717615402.3802 +MEM 146.867188 1717615402.4805 +MEM 147.125000 1717615402.5809 +MEM 153.562500 1717615402.6813 +MEM 154.335938 1717615402.7817 +MEM 154.335938 1717615402.8820 +MEM 154.335938 1717615402.9825 +MEM 154.335938 1717615403.0828 +MEM 154.335938 1717615403.1832 +MEM 154.335938 1717615403.2836 +MEM 161.039062 1717615403.3839 +MEM 161.812500 1717615403.4842 +MEM 162.328125 1717615403.5845 +MEM 169.273438 1717615403.6848 +MEM 169.531250 1717615403.7852 +MEM 176.992188 1717615403.8855 +MEM 176.992188 1717615403.9857 +MEM 184.449219 1717615404.0860 +MEM 184.449219 1717615404.1863 +MEM 186.488281 1717615404.2866 +MEM 191.898438 1717615404.3869 +MEM 192.156250 1717615404.4872 +MEM 199.632812 1717615404.5875 +MEM 199.632812 1717615404.6878 +MEM 207.109375 1717615404.7881 +MEM 207.109375 1717615404.8884 +MEM 213.296875 1717615404.9887 +MEM 214.761719 1717615405.0890 +MEM 214.957031 1717615405.1894 +MEM 222.171875 1717615405.2897 +MEM 222.429688 1717615405.3900 +MEM 229.648438 1717615405.4903 +MEM 229.906250 1717615405.5906 +MEM 236.093750 1717615405.6910 +MEM 237.382812 1717615405.7913 +MEM 237.898438 1717615405.8916 +MEM 244.859375 1717615405.9919 +MEM 245.117188 1717615406.0922 +MEM 252.335938 1717615406.1925 +MEM 252.593750 1717615406.2928 +MEM 258.781250 1717615406.3931 +MEM 260.070312 1717615406.4934 +MEM 260.585938 1717615406.5937 +MEM 267.546875 1717615406.6940 +MEM 267.804688 1717615406.7944 +MEM 275.023438 1717615406.8947 +MEM 275.281250 1717615406.9949 +MEM 281.726562 1717615407.0953 +MEM 282.757812 1717615407.1956 +MEM 283.273438 1717615407.2959 +MEM 290.234375 1717615407.3962 +MEM 290.234375 1717615407.4965 +MEM 297.710938 1717615407.5969 +MEM 297.710938 1717615407.6972 +MEM 298.226562 1717615407.7976 +MEM 305.187500 1717615407.8979 +MEM 305.445312 1717615407.9983 +MEM 305.445312 1717615408.0987 +MEM 312.921875 1717615408.1990 +MEM 312.921875 1717615408.2993 +MEM 319.109375 1717615408.3996 +MEM 320.398438 1717615408.4999 +MEM 320.656250 1717615408.6002 +MEM 327.875000 1717615408.7005 +MEM 328.132812 1717615408.8008 +MEM 335.609375 1717615408.9011 +MEM 335.609375 1717615409.0014 +MEM 341.796875 1717615409.1018 +MEM 343.085938 1717615409.2021 +MEM 343.601562 1717615409.3024 +MEM 350.562500 1717615409.4026 +MEM 350.820312 1717615409.5029 +MEM 358.039062 1717615409.6032 +MEM 358.296875 1717615409.7035 +MEM 365.000000 1717615409.8039 +MEM 365.773438 1717615409.9042 +MEM 366.289062 1717615410.0044 +MEM 373.250000 1717615410.1047 +MEM 373.507812 1717615410.2051 +MEM 380.726562 1717615410.3055 +MEM 380.984375 1717615410.4057 +MEM 388.460938 1717615410.5060 +MEM 388.460938 1717615410.6064 +MEM 390.523438 1717615410.7066 +MEM 395.937500 1717615410.8069 +MEM 396.195312 1717615410.9072 +MEM 403.414062 1717615411.0075 +MEM 403.671875 1717615411.1078 +MEM 411.148438 1717615411.2081 +MEM 411.148438 1717615411.3084 +MEM 417.335938 1717615411.4088 +MEM 418.625000 1717615411.5091 +MEM 418.882812 1717615411.6094 +MEM 426.101562 1717615411.7097 +MEM 426.359375 1717615411.8100 +MEM 433.578125 1717615411.9103 +MEM 433.835938 1717615412.0106 +MEM 440.023438 1717615412.1110 +MEM 441.312500 1717615412.2113 +MEM 441.828125 1717615412.3116 +MEM 448.789062 1717615412.4119 +MEM 449.046875 1717615412.5122 +MEM 456.265625 1717615412.6125 +MEM 456.523438 1717615412.7127 +MEM 462.968750 1717615412.8131 +MEM 464.000000 1717615412.9133 +MEM 464.515625 1717615413.0136 +MEM 471.476562 1717615413.1139 +MEM 471.734375 1717615413.2142 +MEM 478.949219 1717615413.3145 +MEM 479.207031 1717615413.4148 +MEM 486.683594 1717615413.5151 +MEM 486.683594 1717615413.6154 +MEM 487.457031 1717615413.7157 +MEM 494.160156 1717615413.8160 +MEM 494.417969 1717615413.9163 +MEM 501.636719 1717615414.0166 +MEM 501.894531 1717615414.1169 +MEM 509.113281 1717615414.2172 +MEM 509.371094 1717615414.3175 +MEM 509.886719 1717615414.4178 +MEM 516.847656 1717615414.5181 +MEM 516.847656 1717615414.6184 +MEM 524.324219 1717615414.7187 +MEM 524.582031 1717615414.8190 +MEM 531.027344 1717615414.9193 +MEM 532.058594 1717615415.0196 +MEM 532.574219 1717615415.1199 +MEM 539.535156 1717615415.2202 +MEM 539.535156 1717615415.3205 +MEM 547.011719 1717615415.4209 +MEM 547.269531 1717615415.5211 +MEM 554.488281 1717615415.6214 +MEM 554.746094 1717615415.7217 +MEM 556.808594 1717615415.8220 +MEM 562.222656 1717615415.9223 +MEM 562.222656 1717615416.0226 +MEM 569.699219 1717615416.1229 +MEM 569.957031 1717615416.2232 +MEM 577.175781 1717615416.3235 +MEM 577.433594 1717615416.4238 +MEM 582.332031 1717615416.5241 +MEM 584.910156 1717615416.6244 +MEM 584.910156 1717615416.7248 +MEM 592.386719 1717615416.8251 +MEM 592.386719 1717615416.9253 +MEM 599.863281 1717615417.0257 +MEM 600.121094 1717615417.1259 +MEM 603.472656 1717615417.2262 +MEM 606.523438 1717615417.3266 +MEM 606.523438 1717615417.4269 +MEM 606.523438 1717615417.5272 +MEM 606.523438 1717615417.6275 +MEM 606.523438 1717615417.7278 +MEM 606.523438 1717615417.8281 +MEM 606.523438 1717615417.9284 +MEM 606.523438 1717615418.0287 +MEM 606.523438 1717615418.1290 +MEM 606.523438 1717615418.2293 +MEM 606.523438 1717615418.3296 +MEM 606.523438 1717615418.4299 +MEM 606.523438 1717615418.5301 +MEM 606.523438 1717615418.6305 +MEM 606.523438 1717615418.7308 +MEM 606.523438 1717615418.8311 +MEM 606.523438 1717615418.9314 +MEM 606.523438 1717615419.0317 +MEM 606.523438 1717615419.1320 +MEM 606.523438 1717615419.2323 +MEM 606.523438 1717615419.3327 +MEM 606.523438 1717615419.4330 +MEM 606.523438 1717615419.5333 +MEM 606.523438 1717615419.6336 +MEM 606.523438 1717615419.7340 +MEM 606.523438 1717615419.8345 +MEM 606.523438 1717615419.9348 +MEM 606.523438 1717615420.0351 +MEM 606.523438 1717615420.1354 +MEM 606.523438 1717615420.2357 +MEM 606.523438 1717615420.3360 +MEM 606.523438 1717615420.4363 +MEM 606.523438 1717615420.5366 +MEM 606.523438 1717615420.6370 +MEM 606.523438 1717615420.7373 +MEM 606.523438 1717615420.8377 +MEM 606.523438 1717615420.9381 +MEM 606.523438 1717615421.0384 +MEM 606.523438 1717615421.1387 +MEM 606.523438 1717615421.2390 +MEM 606.523438 1717615421.3393 +MEM 606.523438 1717615421.4396 +MEM 606.523438 1717615421.5399 +MEM 606.523438 1717615421.6402 +MEM 606.523438 1717615421.7405 +MEM 606.523438 1717615421.8408 +MEM 606.523438 1717615421.9411 +MEM 606.523438 1717615422.0415 +MEM 606.523438 1717615422.1418 +MEM 612.191406 1717615422.2421 +MEM 612.191406 1717615422.3425 +MEM 612.707031 1717615422.4428 +MEM 618.636719 1717615422.5431 +MEM 618.636719 1717615422.6434 +MEM 625.597656 1717615422.7437 +MEM 625.597656 1717615422.8441 +MEM 631.785156 1717615422.9444 +MEM 632.816406 1717615423.0447 +MEM 633.074219 1717615423.1450 +MEM 640.292969 1717615423.2453 +MEM 640.292969 1717615423.3456 +MEM 647.769531 1717615423.4459 +MEM 647.769531 1717615423.5461 +MEM 654.214844 1717615423.6465 +MEM 655.246094 1717615423.7468 +MEM 655.761719 1717615423.8471 +MEM 662.722656 1717615423.9474 +MEM 662.980469 1717615424.0477 +MEM 670.199219 1717615424.1480 +MEM 670.457031 1717615424.2483 +MEM 677.160156 1717615424.3486 +MEM 677.933594 1717615424.4489 +MEM 678.449219 1717615424.5492 +MEM 685.410156 1717615424.6495 +MEM 685.410156 1717615424.7498 +MEM 692.886719 1717615424.8501 +MEM 692.886719 1717615424.9504 +MEM 700.363281 1717615425.0506 +MEM 700.363281 1717615425.1509 +MEM 700.878906 1717615425.2512 +MEM 707.839844 1717615425.3515 +MEM 708.097656 1717615425.4518 +MEM 652.933594 1717615425.5522 diff --git a/norch/__pycache__/tensor.cpython-38.pyc b/norch/__pycache__/tensor.cpython-38.pyc index ad61d698f8d36154b1e0a24619ee8b3895027531..c7cc0449c24824929c0ab1ffb039c3f3f20a4113 100644 GIT binary patch delta 1585 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 Z#Rqkm+v2lVDQSv~J6axxb2!to?{Bqwd(;2` diff --git a/norch/csrc/cuda.cu b/norch/csrc/cuda.cu index 268d8a2..3095130 100644 --- a/norch/csrc/cuda.cu +++ b/norch/csrc/cuda.cu @@ -24,9 +24,8 @@ __host__ void cpu_to_cuda(Tensor* tensor, int device_id) { tensor->data = data_tmp; - const char* device_str = "cuda"; - tensor->device = (char*)malloc(strlen(device_str) + 1); - strcpy(tensor->device, device_str); + tensor->device = (char*)malloc(strlen("cuda") + 1); + strcpy(tensor->device, "cuda"); } __host__ void cuda_to_cpu(Tensor* tensor) { @@ -37,9 +36,8 @@ __host__ void cuda_to_cpu(Tensor* tensor) { tensor->data = data_tmp; - const char* device_str = "cpu"; - tensor->device = (char*)malloc(strlen(device_str) + 1); - strcpy(tensor->device, device_str); + tensor->device = (char*)malloc(strlen("cpu") + 1); + strcpy(tensor->device, "cpu"); } __host__ void free_cuda(float* data) { diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index 54882bd..9443a6f 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -16,50 +16,40 @@ extern "C" { fprintf(stderr, "Memory allocation failed\n"); exit(1); } + tensor->data = data; + tensor->shape = shape; tensor->ndim = ndim; + tensor->device = (char*)malloc(strlen(device) + 1); + if (device != NULL) { + strcpy(tensor->device, device); + } else { + fprintf(stderr, "Memory allocation failed\n"); + exit(-1); + } + tensor->size = 1; for (int i = 0; i < ndim; i++) { tensor->size *= shape[i]; } - tensor->device = strdup(device); tensor->strides = (int*)malloc(ndim * sizeof(int)); - tensor->shape = (int*)malloc(ndim * sizeof(int)); - - if (tensor->device == NULL || tensor->strides == NULL || tensor->shape == NULL) { + if (tensor->strides == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } - - memcpy(tensor->shape, shape, tensor->ndim * sizeof(int)); - strcpy(tensor->device, device); - - if (strcmp(tensor->device, "cpu") == 0) { - tensor->data = (float*)malloc(tensor->size * sizeof(float)); - memcpy(tensor->data, data, tensor->size * sizeof(float)); - } else { - //already allocated on gpu - tensor->data = data; - } - int stride = 1; for (int i = ndim - 1; i >= 0; i--) { tensor->strides[i] = stride; stride *= shape[i]; } - + return tensor; } void delete_tensor(Tensor* tensor) { if (tensor != NULL) { - if (tensor->strides != NULL) { - free(tensor->strides); - tensor->strides = NULL; - } - if (tensor->shape != NULL) { free(tensor->shape); tensor->shape = NULL; @@ -88,6 +78,21 @@ extern "C" { } } + void delete_strides(Tensor* tensor) { + // as strides always are allocated within C code, it must be handled separatedly + if (tensor->strides != NULL) { + free(tensor->strides); + tensor->strides = NULL; + } + } + + void delete_device(Tensor* tensor) { + // as device always are allocated within C code, it must be handled separatedly + if (tensor->device != NULL) { + free(tensor->device); + tensor->device = NULL; + } + } float get_item(Tensor* tensor, int* indices) { int index = 0; @@ -96,10 +101,10 @@ extern "C" { } float result; - if (strcmp(tensor->device, "cuda") == 0) { - cudaMemcpy(&result, tensor->data + index, sizeof(float), cudaMemcpyDeviceToHost); - } else { + if (strcmp(tensor->device, "cpu") == 0) { result = tensor->data[index]; + } else { + cudaMemcpy(&result, tensor->data + index, sizeof(float), cudaMemcpyDeviceToHost); } return result; @@ -136,13 +141,6 @@ extern "C" { exit(1); } - char* device = (char*)malloc(strlen(tensor1->device) + 1); - if (device != NULL) { - strcpy(device, tensor1->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor1->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -158,21 +156,20 @@ extern "C" { shape[i] = tensor1->shape[i]; } - if (strcmp(tensor1->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); - add_tensor_cuda(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor1->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } add_tensor_cpu(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); + add_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, tensor1->device); } } @@ -206,13 +203,7 @@ extern "C" { broadcasted_size *= broadcasted_shape[i]; } - if (strcmp(tensor1->device, "cuda") == 0) { - float* result_data; - cudaMalloc((void **)&result_data, broadcasted_size * sizeof(float)); - add_broadcasted_tensor_cuda(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); - return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(broadcasted_size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); @@ -221,17 +212,16 @@ extern "C" { add_broadcasted_tensor_cpu(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, broadcasted_size * sizeof(float)); + add_broadcasted_tensor_cuda(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); + return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); } } Tensor* sum_tensor(Tensor* tensor, int axis, bool keepdim) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim; int* shape; @@ -259,36 +249,7 @@ extern "C" { axis_size *= shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - if (axis == -1) { - cudaMalloc((void**)&result_data, tensor->size * sizeof(float)); - } else { - cudaMalloc((void**)&result_data, axis_size * sizeof(float)); - } - sum_tensor_cuda(tensor, result_data, axis); - - if (keepdim) { - if (axis == -1){ - ndim = tensor->ndim; - shape = (int*) malloc((tensor->ndim) * sizeof(int)); - for (int i = 0; i < tensor->ndim; i++) { - shape[i] = 1; - } - } else { - shape = (int*) malloc((tensor->ndim) * sizeof(int)); - for (int i = 0; i < tensor->ndim; i++) { - shape[i] = tensor->shape[i]; - } - shape[axis] = 1; - ndim = tensor->ndim; - } - - } - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)calloc(axis_size, sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); @@ -314,18 +275,39 @@ extern "C" { } } - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + if (axis == -1) { + cudaMalloc((void**)&result_data, tensor->size * sizeof(float)); + } else { + cudaMalloc((void**)&result_data, axis_size * sizeof(float)); + } + sum_tensor_cuda(tensor, result_data, axis); + + if (keepdim) { + if (axis == -1){ + ndim = tensor->ndim; + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = 1; + } + } else { + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = tensor->shape[i]; + } + shape[axis] = 1; + ndim = tensor->ndim; + } + + } + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* max_tensor(Tensor* tensor, int axis, bool keepdim) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim; int* shape; if (axis == -1) { @@ -347,8 +329,35 @@ extern "C" { axis_size *= shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { + if (strcmp(tensor->device, "cpu") == 0) { + float* result_data = (float*)malloc(axis_size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + max_tensor_cpu(tensor, result_data, axis_size, shape, axis); + if (keepdim) { + if (axis == -1){ + ndim = tensor->ndim; + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = 1; + } + } else { + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = tensor->shape[i]; + } + shape[axis] = 1; + ndim = tensor->ndim; + } + + } + return create_tensor(result_data, shape, ndim, tensor->device); + + } + else { float* result_data; if (axis == -1) { cudaMalloc((void**)&result_data, tensor->size * sizeof(float)); @@ -374,46 +383,11 @@ extern "C" { } } - return create_tensor(result_data, shape, ndim, device); - - } - else { - float* result_data = (float*)malloc(axis_size * sizeof(float)); - if (result_data == NULL) { - fprintf(stderr, "Memory allocation failed\n"); - exit(1); - } - max_tensor_cpu(tensor, result_data, axis_size, shape, axis); - - if (keepdim) { - if (axis == -1){ - ndim = tensor->ndim; - shape = (int*) malloc((tensor->ndim) * sizeof(int)); - for (int i = 0; i < tensor->ndim; i++) { - shape[i] = 1; - } - } else { - shape = (int*) malloc((tensor->ndim) * sizeof(int)); - for (int i = 0; i < tensor->ndim; i++) { - shape[i] = tensor->shape[i]; - } - shape[axis] = 1; - ndim = tensor->ndim; - } - - } - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* min_tensor(Tensor* tensor, int axis, bool keepdim) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim; int* shape; if (axis == -1) { @@ -435,8 +409,35 @@ extern "C" { axis_size *= shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { + if (strcmp(tensor->device, "cpu") == 0) { + float* result_data = (float*)malloc(axis_size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + min_tensor_cpu(tensor, result_data, axis_size, shape, axis); + if (keepdim) { + if (axis == -1){ + ndim = tensor->ndim; + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = 1; + } + } else { + shape = (int*) malloc((tensor->ndim) * sizeof(int)); + for (int i = 0; i < tensor->ndim; i++) { + shape[i] = tensor->shape[i]; + } + shape[axis] = 1; + ndim = tensor->ndim; + } + + } + return create_tensor(result_data, shape, ndim, tensor->device); + + } + else { float* result_data; if (axis == -1) { cudaMalloc((void**)&result_data, tensor->size * sizeof(float)); @@ -462,35 +463,7 @@ extern "C" { } } - return create_tensor(result_data, shape, ndim, device); - - } - else { - float* result_data = (float*)malloc(axis_size * sizeof(float)); - if (result_data == NULL) { - fprintf(stderr, "Memory allocation failed\n"); - exit(1); - } - min_tensor_cpu(tensor, result_data, axis_size, shape, axis); - - if (keepdim) { - if (axis == -1){ - ndim = tensor->ndim; - shape = (int*) malloc((tensor->ndim) * sizeof(int)); - for (int i = 0; i < tensor->ndim; i++) { - shape[i] = 1; - } - } else { - shape = (int*) malloc((tensor->ndim) * sizeof(int)); - for (int i = 0; i < tensor->ndim; i++) { - shape[i] = tensor->shape[i]; - } - shape[axis] = 1; - ndim = tensor->ndim; - } - - } - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); } } @@ -505,13 +478,6 @@ extern "C" { exit(1); } - char* device = (char*)malloc(strlen(tensor1->device) + 1); - if (device != NULL) { - strcpy(device, tensor1->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor1->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -527,21 +493,20 @@ extern "C" { shape[i] = tensor1->shape[i]; } - if (strcmp(tensor1->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); - sub_tensor_cuda(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor1->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } sub_tensor_cpu(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); + sub_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, tensor1->device); } } @@ -575,13 +540,7 @@ extern "C" { broadcasted_size *= broadcasted_shape[i]; } - if (strcmp(tensor1->device, "cuda") == 0) { - float* result_data; - cudaMalloc((void **)&result_data, broadcasted_size * sizeof(float)); - sub_broadcasted_tensor_cuda(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); - return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(broadcasted_size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); @@ -590,6 +549,13 @@ extern "C" { sub_broadcasted_tensor_cpu(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); + } + else { + + float* result_data; + cudaMalloc((void **)&result_data, broadcasted_size * sizeof(float)); + sub_broadcasted_tensor_cuda(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); + return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); } } @@ -604,13 +570,6 @@ extern "C" { exit(1); } - char* device = (char*)malloc(strlen(tensor1->device) + 1); - if (device != NULL) { - strcpy(device, tensor1->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor1->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -626,33 +585,25 @@ extern "C" { shape[i] = tensor1->shape[i]; } - if (strcmp(tensor1->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); - elementwise_mul_tensor_cuda(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor1->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } elementwise_mul_tensor_cpu(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); + elementwise_mul_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, tensor1->device); } } Tensor* scalar_mul_tensor(Tensor* tensor, float scalar) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -664,33 +615,25 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - scalar_mul_tensor_cuda(tensor, scalar, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } scalar_mul_tensor_cpu(tensor, scalar, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + scalar_mul_tensor_cuda(tensor, scalar, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* scalar_div_tensor(float scalar, Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -702,33 +645,25 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - scalar_div_tensor_cuda(scalar, tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } scalar_div_tensor_cpu(scalar, tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + scalar_div_tensor_cuda(scalar, tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* tensor_div_scalar(Tensor* tensor, float scalar) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -740,21 +675,20 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - tensor_div_scalar_cuda(tensor, scalar, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } tensor_div_scalar_cpu(tensor, scalar, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + tensor_div_scalar_cuda(tensor, scalar, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } @@ -769,13 +703,6 @@ extern "C" { exit(1); } - char* device = (char*)malloc(strlen(tensor1->device) + 1); - if (device != NULL) { - strcpy(device, tensor1->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor1->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -791,21 +718,20 @@ extern "C" { shape[i] = tensor1->shape[i]; } - if (strcmp(tensor1->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); - tensor_div_tensor_cuda(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor1->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } tensor_div_tensor_cpu(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); + tensor_div_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, tensor1->device); } } @@ -822,13 +748,6 @@ extern "C" { exit(1); } - char* device = (char*)malloc(strlen(tensor1->device) + 1); - if (device != NULL) { - strcpy(device, tensor1->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor1->ndim + tensor2->ndim - 2; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -853,21 +772,20 @@ extern "C" { exit(1); } - if (strcmp(tensor1->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, size * sizeof(float)); - matmul_tensor_cuda(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } matmul_tensor_cpu(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, size * sizeof(float)); + matmul_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, tensor1->device); } } @@ -884,14 +802,6 @@ extern "C" { exit(1); } - char* device = (char*)malloc(strlen(tensor1->device) + 1); - if (device != NULL) { - strcpy(device, tensor1->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } - int ndim = 3; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -914,21 +824,20 @@ extern "C" { exit(1); } - if (strcmp(tensor1->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, size * sizeof(float)); - broadcasted_batched_matmul_tensor_cuda(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } broadcasted_batched_matmul_tensor_cpu(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, size * sizeof(float)); + broadcasted_batched_matmul_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, tensor1->device); } } @@ -952,14 +861,6 @@ extern "C" { exit(1); } - char* device = (char*)malloc(strlen(tensor1->device) + 1); - if (device != NULL) { - strcpy(device, tensor1->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } - int ndim = 3; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -982,34 +883,26 @@ extern "C" { exit(1); } - if (strcmp(tensor1->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, size * sizeof(float)); - batched_matmul_tensor_cuda(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } batched_matmul_tensor_cpu(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, size * sizeof(float)); + batched_matmul_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, tensor1->device); } } Tensor* tensor_pow_scalar(Tensor* tensor, float exponent) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1021,32 +914,24 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - tensor_pow_scalar_cuda(tensor, exponent, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } tensor_pow_scalar_cpu(tensor, exponent, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + tensor_pow_scalar_cuda(tensor, exponent, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* scalar_pow_tensor(float base, Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1058,32 +943,24 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - scalar_pow_tensor_cuda(base, tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } scalar_pow_tensor_cpu(base, tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + scalar_pow_tensor_cuda(base, tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* log_tensor(Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1095,32 +972,24 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - log_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } log_tensor_cpu(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + log_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* reshape_tensor(Tensor* tensor, int* new_shape, int new_ndim) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = new_ndim; int* shape = (int*)malloc(ndim * sizeof(int)); @@ -1145,21 +1014,20 @@ extern "C" { exit(1); } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - assign_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } assign_tensor_cpu(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + assign_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } @@ -1174,13 +1042,6 @@ extern "C" { exit(1); } - char* device = (char*)malloc(strlen(tensor1->device) + 1); - if (device != NULL) { - strcpy(device, tensor1->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor1->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1196,21 +1057,20 @@ extern "C" { shape[i] = tensor1->shape[i]; } - if (strcmp(tensor1->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); - equal_tensor_cuda(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor1->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } equal_tensor_cpu(tensor1, tensor2, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor1->size * sizeof(float)); + equal_tensor_cuda(tensor1, tensor2, result_data); + return create_tensor(result_data, shape, ndim, tensor1->device); } } @@ -1244,13 +1104,7 @@ extern "C" { broadcasted_size *= broadcasted_shape[i]; } - if (strcmp(tensor1->device, "cuda") == 0) { - float* result_data; - cudaMalloc((void **)&result_data, broadcasted_size * sizeof(float)); - equal_broadcasted_tensor_cuda(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); - return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); - } - else { + if (strcmp(tensor1->device, "cpu") == 0) { float* result_data = (float*)malloc(broadcasted_size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); @@ -1259,18 +1113,17 @@ extern "C" { equal_broadcasted_tensor_cpu(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, broadcasted_size * sizeof(float)); + equal_broadcasted_tensor_cuda(tensor1, tensor2, result_data, broadcasted_shape, broadcasted_size); + return create_tensor(result_data, broadcasted_shape, max_ndim, tensor1->device); } } Tensor* ones_like_tensor(Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1282,32 +1135,24 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - ones_like_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } ones_like_tensor_cpu(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + ones_like_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* zeros_like_tensor(Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1319,32 +1164,24 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - zeros_like_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } zeros_like_tensor_cpu(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + zeros_like_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* sin_tensor(Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1356,32 +1193,25 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - sin_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } sin_tensor_cpu(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + sin_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* cos_tensor(Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } + int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1393,32 +1223,24 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - cos_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } cos_tensor_cpu(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + cos_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* sigmoid_tensor(Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1430,33 +1252,24 @@ extern "C" { shape[i] = tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - sigmoid_tensor_cuda(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } sigmoid_tensor_cpu(tensor, result_data); - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + sigmoid_tensor_cuda(tensor, result_data); + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* transpose_tensor(Tensor* tensor) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } - int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1470,27 +1283,7 @@ extern "C" { int size = tensor->size; - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, size * sizeof(float)); - switch (ndim) { - case 1: - transpose_1D_tensor_cuda(tensor, result_data); - break; - case 2: - transpose_2D_tensor_cuda(tensor, result_data); - break; - case 3: - transpose_3D_tensor_cuda(tensor, result_data); - break; - default: - fprintf(stderr, "Transpose only supports tensors up to 3 dimensions.\n"); - exit(-1); - } - return create_tensor(result_data, shape, ndim, device); - } - else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); @@ -1510,19 +1303,30 @@ extern "C" { fprintf(stderr, "Transpose only supports tensors up to 3 dimensions.\n"); exit(-1); } - return create_tensor(result_data, shape, ndim, device); + return create_tensor(result_data, shape, ndim, tensor->device); + } + else { + float* result_data; + cudaMalloc((void **)&result_data, size * sizeof(float)); + switch (ndim) { + case 1: + transpose_1D_tensor_cuda(tensor, result_data); + break; + case 2: + transpose_2D_tensor_cuda(tensor, result_data); + break; + case 3: + transpose_3D_tensor_cuda(tensor, result_data); + break; + default: + fprintf(stderr, "Transpose only supports tensors up to 3 dimensions.\n"); + exit(-1); + } + return create_tensor(result_data, shape, ndim, tensor->device); } } Tensor* transpose_axes_tensor(Tensor* tensor, int axis1, int axis2) { - char* device = (char*)malloc(strlen(tensor->device) + 1); - if (device != NULL) { - strcpy(device, tensor->device); - } else { - fprintf(stderr, "Memory allocation failed\n"); - exit(-1); - } - int ndim = tensor->ndim; int* shape = (int*)malloc(ndim * sizeof(int)); if (shape == NULL) { @@ -1539,13 +1343,15 @@ extern "C" { int size = tensor->size; - if (strcmp(tensor->device, "cuda") == 0) { - - float* result_data; - cudaMalloc((void **)&result_data, size * sizeof(float)); - assign_tensor_cuda(tensor, result_data); - - Tensor* new_tensor = create_tensor(result_data, shape, ndim, device); + if (strcmp(tensor->device, "cpu") == 0) { + float* result_data = (float*)malloc(size * sizeof(float)); + if (result_data == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + exit(1); + } + assign_tensor_cpu(tensor, result_data); + + Tensor* new_tensor = create_tensor(result_data, shape, ndim, tensor->device); for (int i = 0; i < ndim; i++) { new_tensor->strides[i] = tensor->strides[i]; } @@ -1555,14 +1361,11 @@ extern "C" { return new_tensor; } else { - float* result_data = (float*)malloc(size * sizeof(float)); - if (result_data == NULL) { - fprintf(stderr, "Memory allocation failed\n"); - exit(1); - } - assign_tensor_cpu(tensor, result_data); - - Tensor* new_tensor = create_tensor(result_data, shape, ndim, device); + float* result_data; + cudaMalloc((void **)&result_data, size * sizeof(float)); + assign_tensor_cuda(tensor, result_data); + + Tensor* new_tensor = create_tensor(result_data, shape, ndim, tensor->device); for (int i = 0; i < ndim; i++) { new_tensor->strides[i] = tensor->strides[i]; } @@ -1587,17 +1390,16 @@ extern "C" { stride *= tensor->shape[i]; } - if (strcmp(tensor->device, "cuda") == 0) { - float* result_data; - cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); - make_contiguous_tensor_cuda(tensor, result_data, new_strides); - - } else { + if (strcmp(tensor->device, "cpu") == 0) { float* result_data = (float*)malloc(tensor->size * sizeof(float)); if (result_data == NULL) { fprintf(stderr, "Memory allocation failed\n"); } make_contiguous_tensor_cpu(tensor, result_data, new_strides); + } else { + float* result_data; + cudaMalloc((void **)&result_data, tensor->size * sizeof(float)); + make_contiguous_tensor_cuda(tensor, result_data, new_strides); } } } diff --git a/norch/csrc/tensor.h b/norch/csrc/tensor.h index 2465125..6793e10 100644 --- a/norch/csrc/tensor.h +++ b/norch/csrc/tensor.h @@ -13,6 +13,8 @@ typedef struct { extern "C" { Tensor* create_tensor(float* data, int* shape, int ndim, char* device); void delete_tensor(Tensor* tensor); + void delete_strides(Tensor* tensor); + void delete_device(Tensor* tensor); float get_item(Tensor* tensor, int* indices); Tensor* add_tensor(Tensor* tensor1, Tensor* tensor2); Tensor* sum_tensor(Tensor* tensor, int axis, bool keepdims); diff --git a/norch/libtensor.so b/norch/libtensor.so index 300caf16ea98a980e0e99117b7a67309684aec8c..598e06434b5547919eaa721569fca6dc5a12329c 100755 GIT binary patch delta 105669 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

    qe12&R zdF+B<&N5rU$hV*+bJyrZx$m*n5160RoXTvR5+7vV_6_M9=?@ zR>95-5dT}PFHvI42GYu9tu8027|XdjZYlA|686z^62;1MiPmQf88^T6pT@lNcQR)z z!W+QLSQEK4#z5F9dA0Z-XN_5-$x~|%itAYP}e zlt=plysV3+e^FRyJ9QmpepMmyuQ0ERS*x)TtBOZ$na%t~h<4y*X&Uo$vauWvQQ5+$ zLoBx%^ZAPn#bjJtp~THMaPGzYDF&l~FSEB99u&3l+@g)AItt$L)@qw)fGsg`ctXOC z^*OfgRdYBGJ#YiLdc1 zTzQ|1F@B!OzQ%7?<(w89aUW=WdCI_SaU0o!_$RB3pRUqQwG>S&!Kv|!Rk6`xOeN12 zKD?_8Xe2h4yNzumu9mw^Xe1g|hBEJC3my|=W~{FhmyMX(_( z(CF`6Gk_2AujyI?JkrOP4-3|Z0y|jaH`T1!sUovu2=O!eOT3uE1hwS&+IgWFEJ)M0oky(- zXvoO`O0K0_pfT9s78DfX*3Re`9&88+Gn(84gP&l4?)iW?je=jGn|D-q`fms=!wexN zqX1I1+yrLR^Mn~)Z1{!H6%Xw9Cp%-#qiAM$_WE}%)`iF!|3a)be9p*#q}szLUX zjAPwkb-BS%y%5HS@y6e@dbS+M1PgMe?&($UzxLu}04GNUXqS(}ei!mV)x|qU%8B+uw7MQ&VuDU~OSdfveJRcpNHJp6&G zV?m0q-eLE-Ajipo^^jGQ)yELxpTmF+tP2FOAf8{3KRx3)h?4=FQJiAbT!V~$`k<^! z10QCn7pnIgsV5-8U_-D`i1G;)i~+D#pjqQ%z}~0l)%*LyVB?^OBNI>{$*J_P^*X`; zm%N!y*^CSyVhV+Y3ke-YLiR0)A;b_FD(FC5710=ALB@HlTzbkE>@fpe@(N9%G5#1- z5}E-7=sb=F7G&y`jVJpRXu`>WP@STv7>rLDcK%JXcpYJY&_JZ3jM38CNAKzn_TUHu ztOuZ$JOI3j_lL!R58w^BpuozU)vOH!ZR4>ZA3I&EoH#8nCj&SL6|<2{m~o^b1Xf=Z z&305)dmr{E=xYuHt+`ZIz5p#z5)E2Zs+3zQm1Z& zGx|7KkmXOVXH@Zpk!Ap^vPi083iqW|j=&t_u^{(HG`QZA2XBP|tjb-i0^W)s)v=rd zHih0$5WW4$a`wKtI2mAdK1$65hX>JST7j3xV?my-Z}`uO;SD$$U{#{gL|`+apoCzt zX$xXAZ!XL@dB4ps9bo{gGaKuGp$`+n4gUOS+LR)Xn9{=PkAZG3}97WVHJDo9)k;G zu&PvPpO@Rg*a{qBfKq#Fst*M>QZfjdiS^XSB^QqcA%4?}mK4r&GGG=O(>7HmeU@(c z`G);tbc6vyTahirLM*z{*>%EN*by;6@T4dfSY&buK~Rtnh5KF^`3AgU27pB9_M{>F z3d$$#lc2Y2pb{;}=NF%*Z0!&8f&qf9NOm!jH6q!e`~qXGA}@3@Ad$6vMY2U1S!J(f zd4+XNSocHM!|9XaUIR-KAl2o|pl%nE>+&H1u)DBe+rnt9Sfgli>CgwObTYsy_QQ&{ zP|+XN0sbeK5QP=I3I%o?b6}!Q2Ecq}=X2wR5xiCt_0jr3O;8mWM-yF?c7x=GE23W1vSSz1c3u<)38nIYofTOqf#;x~tG5}pI4zrOD z@iFlsB*;KQ!_nZvdISbH82)bM;GFDwabZmS0v%xhG>B^r-xM1x;wu>S{(gE>m=Bw& z&vB+=L1Oks7r#^+3@-y%)fG@xhyx-Z5XFFShf4l+d~gAdFhFQ8q9}{lk^Z4>l8!Jyb~AQ?4M{KT7ia{V=z~i( zmLJ zw=JyJ_6jEhW+7B;Q;9&>pWn1`bJcx1!T=#mL{XgL)QQd`^Szv>BMcBGW<^=QIe$c> z?|{MpVKznKcOWxZkokP~LQcpG1FSoz>|;ZXp}%oh1_IkW7Ub2zm4njifv3d)voJp^ zPebd}GZY&&7fhD~Fa;cdWUwG>g4>l!ase_7u;xi|Lj8>4A-~ZM)mm15YE7?kyn{Uqa9H>o&o5Ptbhi^6muN()juIQjaz+HM>%m0J1Te69^=mKKkkaI9NY zHe~(=CB}p?I+NPXRV`Te)^DpiqVp0RVE|47++p(6%`JeDKCscokvv%Goa$LKqHIjE zZsv1h#v$s*nBWCFb%X&jGc~D2^Ebc_Jj{p2&%i!fF~q9Kb*&jvR1zF_Q6>F(KZF$L zzdyPTSdbfQmrj~H)rFG*vx~F?IRFclwAr(G_sYAsCv5^#p#* zC9Fd>>LhjV9k3O4ybJ)Y>AFS52a9x&-emGInEa^YW+{jjH(*7t1{W62KY1F~TnPY% zXhlDiyPaHxdZ3~kY8O)ZrMDBfp$xE=w=&&e^B#=a2fLQ65~o~?tc#2EMz%?aw=y2aX>uF|f?IP1X?x2%Ra4%DsISbtYm?|Ee5efOgl`WALV=lHW^mgaJ$==-%EA zBp~U+E;QI!kPiQt>^7Z%0b~I5ztw+iUs|1%c`hyYl+|R zq^=-b31DV}KZ!V4kQPTglXL9>90oAy+Q6^r4(No46V7U6#oh5bwoP6Kofc>5Pqc>x ze0Y;jgn-*S!K&Kh7N*v1onhO=0PFra{a(*`f9oj|^QCRt!lJWvgaNXh5Vw5cA=tiE z;|x=-V%>Q492$o$AvjYZeg>RppT@z?2@7Idt3acS!l@j|yps4a%qta*Ri^Gg>RFJ{ zL}y=B(2R6D2-k|iN>$+H)A8#|4{ilB!2oEj!+&WlOLP%++g_!Q7z+^B@bP=wrFpE{ zrXvgxO2Ka+RYm=~Ja8V_zu_*3iAjK@2^Neer|0KQvOg7x_6ZBpCpzV|z(KHz0a6`d z4%V>)%Y!QsG=m!kTyfl$Dz(Ttb+w<<{H!3b{Xgh0~l+6 zU>yhEq_S&Dt+%7jmQE3155@r25(Z<^3qbT&fKyf6np!p1d06pL2Rbg+5eBfvK4UfL zQ-GikMn_(0iLsTHKi&o>Q9d-lG(b}wCId1F}1+HH3r*!>ICG z@?zT%{)L?c227QajsD)mXX^ajI>G>8mpXL4sWZi!pqrwfuMD;Bw&SR8{xInokRUoi z!eJ^IdYXnVCk?XZ25LMOq)f>tbMNf|W6S`ln&koZOR|9qXX0`a%hr`xG%eKCT8f>q z58xwxAfiD~J(Nm&qF>k!JwFMYLkR%El*z^j3-myxGRRj5f!4u+*a0vt$lc{%r`&YT z&&dGrnT#x^LXqwO0WTQ9F!9tu3FnkHT^UfQ5(HmXcQ2dg%c!0lu#2@U2CM~$bAj>WQw9%g4AYqbLQjgKGF?sGel*%&6#~r+5c-Hz8sSk47UZXS z*J$6-%^pWovwEdLJbUH0T(4ac6WUn?)=z`pcWFq!re+rMq;khWz(D1;0ObNuL{7I1qTLp zCg7rg8sL$Q8RjxA$kx-}er@>S&B*|Zx+y6OJu_$bJ6;Op$^aNlB+G|Echl|Q5L!Iw zSD6&&n9MOx27nb}fZz-jpy4^Fd03Dt+uRdva+l|1zPAeP-3vkl<^5Ko+ z=xza%5O{iuRRCh1dVe27q}~tGmn@)VxrDD!ki*|E6uWaPQ6~c+Sz7H3O4bHzfy|oV zc|8`S!L2Umgs7XujnSHv$&kJo5Zkf@-ys(EMOw@Le+!!bSsv#29NczAdm88Y`#AIhmP3B71CGV`%A~pkwzd&eyB}K&v)5yIO>^B2BeS? zJp&LA0yh1s6Ll}CI7b-3j*X5Y6?>%eGa}LXO#mGIFhIcb2;kqIqCi0&ta>tS`TEs5 z836w2LcR$Iz+jsA;85HtTXa~ZAX4q|X~?YU&JaK1j~BiebTBu^V%5renzYw8V%v$S zI>G=LKwN|^XxY>A(UTrnfi2CDXb~hTYUT~5qBq#GZCQ;dqS*Pr0FxGE>E_(EU)jMq z4+EqI_=?E3O_(7F7B)*7)-8_Yi&Z9P8^nCj$$+pCeghO|L~%qE+sh%XBhFobQIP-^ zU(XG{3RsY!-j*lh3qY_ipzDcpdib?bPK3SOD}<$GXiEJLdK=P zF&GYeO=$EsBkyIg^H=_P(SFk3?{qSt4dl!{*7^GCK=3bpbNw|l^V#1z;SKEwf37UZ z2Mcnfa`}CG{%i$@O%fo?6j77|{0RYXi@v>7jUxV{5pcW{gW*_^h~aTF>eq!t00yvw5I-;gJQn0>nT))9PJsu*0OrBOj>!#<5fo(S zq|FPQ+~72x0nCFL0EU9cf|yhPoNF6hi<5!>c})hX;hH=P7FSx3WoshFWz_A!$pHEU z)OPH^9-~hX!TV!&Cbe;*p*yoO2AIkWfE^2u z1?hRWNZXM5b--bgfd9Q0JoPNzASo#lKkOmiqArHlbG??=%sz;S`I_j>2abUn0IM}{14YW$<*JG9HRQaBwAs1zxt7_01A^UQIF z^M;+$kucW|Y0*b4S;9~`cxXle<22MCrv>pNYY+LNoo9eqGThW=i-tR*S(U&g4bSTc z1DI6~K&y-exzN_RZ8Lw!++cvU9G!n3y9tGDEEVKv=&yJ_d~a~b^tgnA9ASVQ(#`?L zy1^VGveJGJ#jpkW$AWB*dp7CmZt!k8H4?r&|2zVs=$(Nd&=tid_N<>6U)~#Vp6B`g ze!|`noN%0?sDdp&?e!g_f-XZuqr=w zsc4Ky`U!sS4UuIIeO@d`Z`&8-OyWjP22kColROW41gRJ_H(hj<=@KNm*0H(Q2W**k zPe&Lad>1>ac+>7z7FT(+11K}Vn#F3_vxvv4!QeTXOmJ?9Gvh1v84EI}m-EY^9pCF@ zz$|3aMpdF4QY%ily%hLj0Qi?xvWXDTbQ)|0Tx9f#)qz^Y!F@Y7bH(M>Pa#Mo0oGk; zD5pCrT#E->RNC$2u2>y{DiR{3%H$F||Ac%e31A&kIn3-Q8ONFhH<^V90bE$Ibsyg7 z+6N3v=N|pV=&ZVZVGIfs3$Vfqh91}qhp-GVvpq=;IM(ggm)rM)$fm0OHsJvQ2EpLp z3pQCaVOBl`R*k4zKeuwTZrO3_6-V{$s2I$U_pZ7PVAo%JP9)7Bmh=G zI&&%k^AfsBHJd&?w(R!gbqaZF*4<@EBJ1dV{!i>HOF)eAJy&URI>gE)0EO8Cd&i+L z3nEz`qu^r-GiHgHXRT<>m?Be?!7%dwk*S&SZzhe=!|@RV&`qFBO+g`*r7~5mNeoTK zx8_A_*XYF%R|wmq_2-S?;?aV9X%{xw-#vtr0kbweJgh|9ve7QEnPC7Ji|lSrQJ

      c_4h)KFaU?O0y1-$3Wqm=0z*8A-e?i8wJ=P%ign}KwOwpnnhYaxDNqD= zv)k)D51)aP!~nAt0m});y20NGH-LuQP?^%2!@y!eJSVgrd#xWN#xcMwR27A*tQF&q z)-tp&o1h~MfZ2xKN|5f6qodQ=$0gumm;?x}l&tE`$&9j%UtjhB zmz@FZ3d3czLs*a=^%@2Z@&b>70ooX&!-CXKf0l#bJOd=nFS;POQq%6N4|A>`*(9K8 zV?VurL%qAcJ`S@Y(_v?I6?VV5q9Y7IlZMIe7Eh3q-~kZKryTID`KhNdu~OO$E|@-@ zd$fV^v05q>g$wR?{QR`dpLFCIJAQ}k8Hn*>>p9?9x31N2FvUVR+=~eh!Miuu zb!DM*UDq#IXMP1&Bqac67+qa9;CSGU63jVX*7FIZ615V9o6-A2i@snD7{Dt3z{>Vg zz|F0Mo;Rks3V4f7_9#@RJ5xH9I4jiEafAV8Aw@GzvG-=~KYvC?f+av$ znib_rrdQgM!O0LrkpN*uR+I+Y*11fNgWx9vr05{O6+}!6lGeAznxz*Zp3DI29x8VO z!Q@ES0-=N5r0y!+Qz(XAn_WA>9~>qIn6<64pJW{CR<)Z^P(yu~Yj2;5x6Gh4K-lvy?#F(C~IT#kXMgXaw) z2Jt?RqB@L#Ov#!p7mbXNBgU4PssUF>sp;f5tR2KS7d}7u2lTYXf z1AeFL5+%@ex{b&u5`%?9vE+<|Ov{?Rni}>@Q6^V#Vx_AJ#*iR*f`CSE6xHb2aq__n zJ0L%R0cPPG2-0f7Wk1O{*6nH+ENmA7H#D`wS{%+JzZ`#j8axdK;BxB$4f0-~QsC`} z=zZ~gMP(cBjH&y`kx$hT27qruYxKk#cK&#OI7^j34E7OeGvE}50sjlbASjt(MLzDm zN{-?t&D9YGm<40jSr!h)3RzVDwuenP~b0m5*Kq7rSF#f>xmZSw`P zjU)gWPlC~)+Y8|cDuQ~MDpsq8p>PdI8|wCau!HB-`!r@s$Kn-)XVVMOL<;7MS`DJ6 zCbmS~tQo+Rc;u<}NJHLVndnj@A4d+_`;(V*%0h&%s;HKV7plRLX<|rCaKqlJUA?he z5_|X5!--ACmI1HLlm7+ZGE=1a6}yZD(cs85@d#Y_7xC3Ji}np}?Y{LVTrny0w7MBC z7MX=!*sj`J-kE=V)6JQ0bmaEuMsBO4A)PrM+F}r)uDs-k5G^^=~21o7+9?Oey6IXhQogPBhe4QfvCYxef4U=s){*Rjm}W5BO{>(p(4sP((5= z{bGsnlOO5G`97ig4VRwd(E?@jHqNbrc;`6Vsa1S~&60ID;Mk7QmU&UGc-RVsP<~jD ze@l*CKBWds`W4CTDzAB*3wUWI@{$9NOmi19V~crdCKw52ZMreMK^5C{$PQwFOf?4_ znW}QTL~U-m4|fPV-4-Hkxsra=4KMMJPF^h5z;Rx>9h#f0IkB2LavONBLD-HxRktyI zVDk!37vIs59fi-%Y7&bh6Ny@;9&HVdOcRGj7%gh0qCxDU9H~3sE}sV-ZA~(_21lm( z7$uDNP~mcyk6&11FcGXIEgn2y)sdZ#%fFoWHj^4*U_qLvHALjtn$ckx;6XTA-K)=_pSV2?yY(VhF2pG z4USCH4wv~NqGRCW8zl1-1HfsYK9JvAXa)i*V0&Aik%nW)Y)1gHTW`p^ofK~S?T+R)HN6%ffIWE?3+B*ZO+&{aFkZWWN>E4A%LAf~QAR<7FLweT#}Ha)ovHuS zyf@P@8Jr;3jWG^$5?f|BQ#Cj;O|%$76n0cS`xgYo-CQ;bj`zwATwj6lEO%5GkN9d! zpuv~vA4mGlM4s)j(^!xZ{a0?A+!^wM86e*X%>hTIiMMx!1zF|r)@jVQ9tFT+B{n`& zB6WNQDBx<+R-a0yAjji$TYj4M7yGd)FZa? zkyEc#A0~1{cWY^ArH6kiG!@O#;2_PPK*>@U3P@DPL`ff-3JSE9Jxk`e5l6xnKn%&y z`c)gZ2XOY8Al0K;anfkzfX~_yW~ww;S?sSDd7bX4x95n_!}v@0P(`1ExudaFrHzY3g zzx}>^%lTCCD1LDn-$vC(4L;H@ji@y7w=D9bR_xqU?<`Kq3(TCc#`GS2^Cq*3UvAk}F)}M8x*O)7OpTGG` zqvepEd#d5jKl@zBl*0i+9%Mc*3e#3aa&=Mf)M_K=LPEV~eEw~@<^l6!I3On+rZ7Sb z(v$?QDA?4l1wIxT4M)EWkS9(KI5N$JNK;fo%XySeJp6&&-&^7hX$|hd@`ufW*VTcE zBUwLsRZY53Ls5T&FArihq^VJoZKYDid*%V_y0G?m*GVPaK@O$FK~xk;gTrX@m5^te zeWF(EJTnr_sjFe@{$Z2dt_?|OKrj>pilNZd;K($a18RCcdI;+e^JN3FjRiTsC}P;B zwy)!TBU;O$QD!rKhZP81p(q}ddD%;Sx7 zVIK~Mt?FpL>G<;Ifm8Jy3GXyC!uS0YYBwnUdE5u%>vV84N4k=%oQU6lS?kM{NT@c% zdDi%Zzo&58U*z#JL(6WL^5SzC5lqbNsYCa6Td%!_dv^g9WD4r zGFV9I;RY4A8XUQI_~3=GmiA5+V6Eg+EwS!8V3V7*Ch1s%JwP)Banx(221llecZP-2 zS!r&#x;(CLTR0*wvFgCILBoM2Od_#gfS+C%Bqm-l)@Iggs>)4G#-=n&{ntP9H1Bf_ zLJbTs3m>zx&wi3|WSX;(9S8c(BEIPhQ4CdddSms*d4^Z2wR8-|T9JET?U60akxenxrf z8mv?pPD3VdK>@m@F#N{<%);=haBq&ij+c!n*>f)>$!~DCQ4QAVgf&@J+B?49qkJ5^ zCR5>gP)f`D3$o$N(=+y9Zws7aHIJ+RXm->hg|oFlO<0#z>pgZXue)R#c%$OgzRNUV zgmMxu863f$sBM@AUsfW#c%?l^I`PK&`L}~`6W*i33)_N|uftFs%1Tp%Bhxe?BexM> zEzOBfHg8=16=E%pV_#32J~P|lXBYlR^ZV%q&f71`X3DfXAK0;C2RJ({QfSl0e2X?_ zBTZQ`KYx$g-92-eBF#ID+{nB4mUHviIqc$W zI5RyR@7aALpcEpFeY{uYsDYyJR>+*uOYp*7k+XZqB^IR6_=FDQQ(-UnHT;0ngAo?s ztTE!)&|BKHke;D}7}?s&=l4#(`Anys@8UIam>V9gy7jIyJ3G!cw_ogbFJd9QF6}k+ z{FVyK70yCHLm;FWq!0G>*WV2GcK-JcHsh>w|RaAcZ4QMJ#AG?m5R{wv|wVjq~) zVvqNNNHquQ8XTGCYoz&SR+?^M6ApKr2VUMB?%suFeQyCx&BCU^k!j+?F2XTNQ)Ty4 z>@yrXK5WgAK{30wK1=Y1zVAgGb>8Icb2T1?cLtnNWK+i#j^3PruPRz;$H5x;OIOc) z52>~1+D;7mGmpG{&?l&+h$z3^0frO{V!qk^Xx`E7IC41JX@+4_H|o6rQE8vMM`R%f ze7Rf7Yt^7Kg-~UnAdP}2bQvDn0WQ?N;L~isVYe`m54v>|aj+l>zKi0gxdYB$^bLlGbp<@_LGcb z-M6}O_GXw-dUO(AJo|m)xU&&CTN zb7I5r9uIz-1Eb9)QCYAcXF4yuJZ->p*uO|XHhU=clZ<2Cp7!RE*d9Jy=1Z?uSU1_L zdgoy+-@%LH49KQQ_LGc*P0~mw_=`TC}A zIS!)JM6-LRmTi;x1~wB-lQ-_{mVYM)z6@e!3X-89sf(DTXhNE z7qdpOPoq(Yj-n8iFq_>D-+|+s)P)x?Bp{p6Ap1$i!G6eqk)N{8(d|Mi#65~{p7cO`>#Nr2fT+VrFL|Y7DPQ||1 zoxP9Hc1+ECl>4jnx#daN%4D8xy7g zBsjk7b>eU6do#pQhcPrbjHU&nL^P$|pQebZZAYsQ^WE}(hS&!KvPm#vKgl?ZFuiEP z24As93sOF<*u566II|##S-@9KteDl{$TWKZsy620(`$Rsk+Xw2Qe)nq6}R3VoFyx# zaaQ^oe3`xxgdr3|e6<{ocS>B{{uIQR7?6z|*iSMJ(rf|bXsV*%DbiFFHoW4xggI+Y z>d5e4`WYWAc;3GPl|?-{H8?WO_9%yCh_BvX>SNY&T{U2BliTLDTZNGv65Z+Y8M`!0yqW1z3CpdbJ`=l}pg&)R@Cg z=gvY#qXgiNf#RdtV5hChlx1i#zD)le%EWfGJ}BG(dlKbpz{!fb1ed#za>f8$Cd+4& zl}$gBgDVAYu`w?j0&_n2@u?hWVe9aKKrTybC?FgGC+xm(Ls5F7%a%R^FTMr;*TmDe z2DN~LPX?H!CsA_3VdMoo3>2U263?LcGQcAlywPLbwp?8}((Obm*U>A%*05(*N}=%3 zZ6JTn8U8h6x)(?OF5>32z4KsBh=4!C)K>hZ7mb zB_>7M*g-QGdsOUNs8k19JwxP zVgWE03@~foq+vhFI5JIKE(JXAgT5;?onj01+fGEfN_&)0`kn)hO!G9*NiRqz06fD7x4-Z#L{XR} zW8&RTR)vrY18~yfG~iRQq9d&cUpa#ZS%TnmN$^-LJ}sgcC-D;%VAvRtAXR^*RF^)x zmtFNX;cHyhJ&4f}2FQG4^TI(WfL*1zm!oIzo?jYXZ<-xj!{8Hq6!bMrly43=GEL-3 zNXkmn9H{Sjeh*|;Zz(b|Wpm`&>}YCmWSV8r7KV#@polf{d4z7rS}+lH>ZN{s@-R1y znP#qPaAcbJa-r}*q^a0Tafv;yBkw&|Y@2IJ0X`GNzANo^+w$pGRrmF9sVg~8M762g zb=v9t$NoL5iGa5dEv%rB=6u3+&ov zH8^rtFwargl9lESyZtR=Jz(`8c6-ssJYyn&rpD}OaFC`MC|NLTgn58U*V9^hrG2^x ziFORYvl+za6TtMP+tSZ`SQ$%(DA!;uh#9+uMMWusN`nO{G~NEz!uJ2b1<5`aK6;P+ zqzr&ENR{pEBVyX_Viyee>x5|Ryp7<6WUwHwQy*{0cnCJSQ~e$bW~O{#PdBO5ye_}q zrA~Q>84nqAYj)S%V$2x(BED=e7D=jCBPV^Sqx045nIGgiMQnB)R>Fd4 zaOB?l16Sz|^pH~g@QIpq;VRL~zrTc`I+;{1By)c2>_}^H7-C*B@Vkx-J#Qel+X`FD^5HaV8XnpQZht>M^gqp>d;yg235?wP)Hl%3l?FEAIDr55T7dsjxOr zVVyI)b{5|K!(iXbWjNsw{AOhpjmuVSdziF9M+zRym^RaG1s-+K;VTQ6(o>q4$BjOT zYS_id_zWHKw%jVv=JFh!)Mra=?9eHwOU8`M(>(7?$W)*Hx~u81+jFKomNAHuf+*we z4SwPM9Nu&rQm(DbTPGVDe4wo#Mw~}bfLEowYFcu0tpZMM;kn8+lM-usCgKPOBaRLK z0VXdk$l;GZlg!WH=5+G6Bwe#QuAJaN`)sL&Byo))4?WICGL2gssLrNNP%5hRsMTe+N3ULhv-^#U+r4e%HdzFCYh1wF6Qsqr%p(p0*w(EJ z@-HlR?lltuzYp2Pf{d!zd`xeL+8pUOHR_Q$qM;%J901`YwrVS$5aKZ*sq-Vz{orw! z**^*oaoYRn9n5TL{?Jpz>~UmO8jq|^fC9v-eE;X=*248dC&INxU1IKgZ!=MqCL)fF z>Rr!?9=)%mO~0ihecK#y`eFY-?#c$>kjH{djkB$1-6dcLW-2+FQRYp^#XXQ)oUG3`&r*)#8N!GDNRI#S=SA{w? z9zS?-t`F=HJOPb`a12|uQMtQAdK76`e3dgtnqAvw_NvsHV-HA`1We0W;EtRdRx{yN z)%w6#MC~ev4~d7JR4pIF&suxlI;LH}+21be$fRrjQzPs!^m0UOR^d{E!^Xs70h;i+ zB)E_n83x0$50(I0kcwl@4E5~o&dGpT_#1GcHwxK9KmW;7U>7VU43JhH>YS$A(#zT~ zJyTT>Y{vM7Hyeh)6)DC(pwqL9B^1y z=<|mx=20B!V?p8_qbm+DK(5-oyS?YG?@&tVin2f!nsTS`4EuL*pQYNM*T+|XVza`s z78T_Zl5sIiZTzym1H3rd>&L>dzlzFT;c2*GJ&ve4<)?o9-}#5FxB-{E>v!(GX)Gpg zOA}l5g(0mk%90wHjDER96My~(y~o2AiPx;n2~egDwInf*D^ zu9jd(sE*A}L>wEc(&7_m8XTD>zM?HWQFR6TL+o;0FLtjA1i*H0YVc@ck5k#14GoS= z6J15&C@>4!qu7Jaqx#Lg+YFYr?Pa;GSGysf8qZsUgEVUZNA$E;Ks#tf^LoROc6a&# z&66S5e}s5d2AZv~FKT}v{b%!gdwRoeXL7DuhIKQNvN`^JyCHSn>3DbyOw3)aOh=kF zdjhC|SBFVx;s=M-`zXWq!lP!5+pZ%F$R_=P{UqbaJ*tV_!j&I-r0AviflOFL=k1D~ zv7o*)^r!^(THPZJ4${PMrkGtBLTRd^G!<`t+7p&hl_OujkGXR6LL|`iL>zS_M}vbj zp8=Ky6EUUD2fqzip#>@asytWiVL8aU*_GPPv3E4kOrbPYeW`i8yK%ixc(p?U%-RQ6A9sJescjQD zjj5OLcs=gaHZCgR3=RfrcjmePEGiA9T%c2eq&umjZ6D z`g#X4=NKULqheLPeR%zTxX0sFa0`F|?D2Qy_12IU?|${a3oac4ghArqC})xzz6>}T z{2DHbGC(K?Lj!6bk8;3*EPPpM{raNd$S^>tAfn7gwZVdH3d+?hd=%W|W`HnMWLJ5c zc1p2~L}&a!5Ca6CtSFy;HmtUIC-`;@5a1vmdBH?uT9E#yw|#qU5BI|uAm~LD<#pG8 zO@o{5DF*B^K=2n)@C=*Bf-HI8D}G^NcuJQ6LZFDE^r*J++38%z0EGddvoM^wECZmx zK(D_+{0Q&l(m)jpQf_3S;tP60)&m3Bo3YAAUOyj?ei&K;mNo|9RKVk1%N`&rxu&Wy zcB}Hjvr{>E3Y`IFHpmL6>?auqX(l7NR4gn|fc2b?Fx{U2^Q7j=g~z-g!S~nADpkv( zRl1BgHma9WDvv#t(ccx^OyT^?P2L{^IhHch3V0Q;Ajx$Oyc=5^dfV>GrT2DcO!Cv4 zbk(H``S3m`%|iuvHh+_Q^2$#wM^a-&dwU7FkNSS1SS<*Ds89Mt( z#*uq_0%;b-o~YM~FTZ@3^k4E#N9Nn@Y}~bbws(g#IBZnJxUZjEsKK(0NF!qy-!)OX=NV6mIV5>UYeOsegyBWuU&)6m@oAaGq zCG(jR4$@3Uau`iv*H%!J{6|zJw~QMWPp3f~*&8^y*p(X(faX;A(W>tSEeW2@*R)V@ zfaEklveZG6s83)glu7Z*|HYu!A0f{>>TpDpQ(OO%RgZf0OjLEDb@5o+x6grIvD-Rx zgaKw|o^rrpqT*`-9Y#~(;p2uOvFi`Ff?bdVn3+|~0Y|1;2Wg7pSE>IjbG+}Kb8u2j z3XM9vf7*Uo{5j#s;-@JLFHu&uJVv}}L3$NS9aJPY4C%I>TQ=l*1>cVY*}|_PtM96yGl?4&Qa;(VQ(@^}*%Qt4hWmb-_Yn(H7aof~;>- zqn^`yIP}@mVB5&?wQEsr*^WQY!Gda+I*Z1X8rptPF)&o8;!}>bC=a&?Km?S&qTuQz z7!5v-2&GSuzGPsOZ9vOP!yGD)g~PH9Lfbc9C5pf(-vvaN5INug&CIs{QLgfbdQhb5 z#2m$od;Yl4n2COlusG*ARjta(OTg1Tk*6GRu%9$}CkFeu9fS|YSuv!`R+KpH_M|5~ zd9$ql{btE4NxJ$Un&d(xi5oj>kmo zm#vt9z6$Zryx$hJXwnLfrdb?uB$|q>zHYxgKDw;Xq$TYtqO$-YGpA>%#@_DH1*-nAOz}MWgXoFX;H9#{VuaJSVQpQw0 zHP^1x-+I;s?oBd$CI*FN8Q~-0_}Ja4$Ug0&q(11uiK&QJ2UPG%IU{f+Bk4!E z`86=VX#w(Jqe?~8;2=$0I7E+V20&K+!mneNTa&zxfmfZmt@GPBc;Em;=mA*tv#o+z zq_3!w24AM1j(kd{Ls9wFgL6M$zi$(yrGD^y;dvF;y1zu4IpD}NQ-P6myKYh4;Pyh0 z72jodoZV9Q2Y8kYK)!*nWW;x4Kh^tVh9=|7Z75b;J+1zlS!~L5GKIacuY=9wnym8G;2_PyNE2`4vNHzd z^ISW|>YS&ifX+?1?A+s?C+M6oiPGdJ6og7xkfRU(`lTzgoFg@RKChAxxq@R|QHG$> z@vpXPQ@|y;{AB8>hVDbCs?%nhVzY6yE2>X^{RkU1AoSm8IQ}t@Je~GpEHv8@3n${D)!}brWigg056)RCiXxFPm^J zo`BS*1EzpUC@|{15ypb}6zH>=51#_>DGb?Zd$s%$M8A*d)UT(?sz%=tQ8%ofX%eb2WGO5{n%;^4-k$r=CvCRdphCb2zX=PGxzFTjNjz0lCzd)s_ z;(7n3P0f-63>0KH zu<(NtI0!!6Aht=X&5*SBRdRPMGeVEIsv=vRL~@wE9qPWzR- zzALZi_MQ*>g2jG4X15zYQ)w1i6`s>(RRUYvHfBz}PzbC%*jMnt`8_yMHA2t+!+y3rngfC{Lw`DO*K3MFnqHB{6*K1j@ z73j{ue&?avVrb)LTVt|5=gGOjU zs@?DMu4=pHoD8ryR!%rFO?pNu%2vf^^saWb8s}*Z_huv@8$Q`jGLB4>Zap=Dl%vP? zEN)l;f*$KC2G&@(XeW%96mO$88w;Yrk!jY$8Q@H3p^DGO10791NpLi=xksTPq&3iF z@>h6JuLBxp1K-Dtpd;l5vn`9bl0kkMgVw5Nvy>%3whj?>GDPxCz1as#~KLOl*K@%Wn`zy*=A< zEO}Y*^K0;|{=NNUzb}5FleQD80MMY~Eyvt#2QPANu|C!V@n3UOiy>)V||Kozy=SmD+JL!<*NFOt9gdC*`lQ3aIqU z%I@Z)?Un|-fMdXd1?z11wfM14I;K!j`D4k1^7*<#Lw8H`eemEBBqK^^Q7%AC49gr2 zK72nm;i`_6?%T{X%km|A#mi5ftqQ;$hymMnnu zw?bJvo$s?S@yr&WGB_^!aFYr^MV}QV!vj3=S`b(X37NtTNQaSa;w|_w{_ttN#I-)aN&Mua&A2K1;7I*6%%po5B@YH;Ma@&ajUOlr{2 z$(}>Xfp=t^?%j6RRyzpCXiTaGN2a+1X^QhtWmgW=z35&v8qQ!DU}nmv*eCXrjDs|j zp*N~%uR3+UT$oV#z-AkcBwfniXnUV})J$JQd}SF{&&6raD{S5Q;Wm68u8iCJQDvf?t338_ND)X`8RUNc@$=nwxTVUn_N&+O z_>^Ji-!y}3uUFG5n0uD8r>+vN<(5gvsbr`W_jPWk3EY~t;L|X`%novMz>$S-P-v?5 zN{fCq9a}mc&bb(1W^-0?#o13X4${OxiRCyHa1VA=xWNz&w`){%CuY3L{C92-xW0Yw ze4O86_yo0f52nFkbcG_wt9Z_*Iv9?a{$l&Y?GOvBFgwlmi9c*e>Cyu$klWDd*i zp_Hkz_m1TybkI_6dW83zesu7%#97qm3GrV73WUxb0Q=?Mfey zeu>>N*#=@R=l|_ec0)A><#K5bI5JINr0E9*@LUr zonoA>R>@G{u8AYNjqQo&jY&9FJsE#hbpBq{4NyZ$=m#IG4rf|R?99wslff&*?DYat8R0v88D71Oni$yFpBD_Wh z-rzW>qe||v-uH`!On`LB!WDk>UO7YF^H^4(45V`bdNPLv2|sAqXxqU9lD;K?9onki z?PEX5II>*nL=K>G6$sMDg17}wHx(QMj_H^Yg-xI1rcqt+!k?#OL3vQ03;2gOn}4Ja zd=z%|#ahF5eQTP{KG(kOTc^}EMi5jrr{`r(PnEkxKld$+0J<>e6{)$##JlyKIto%z z#uVK2H$NSQwkP7KcaRz!)-4NePKB40CZAFmK4p&unR}|N%Xo)t963$+glA)~Wv4Fp z8`XAQ>yCN_dtnB!xMnp+ z&|NIZi>l|7zndm=GQhHhl+W?Tt?uMjkq>}x%SZt8c|X<$Dp(MgewT(W?Z23l0p@Oo zVwwpSgr9u6HFpm*ngJ{|NNMQwn#W&%jfKU40W53e9|xd<1?hF{m7~`>h{`ZPGVQ9! zYwhHB`oR4CAO%JO*ov~c7Er;0+~~f)^SpQP={g3m)F363DI+l9fPc*(IHZvPb_lNU zvSG;Qe^%m3( zz#b@KK}P2OcUz&h5CCBS%T1~X>kE$s@p@m<;rk7U#WH~9CVfY~upkd#6xw|>6Zm2P z%S}?Evy*ZcPik=h9(`Z{OEe0Bn?yVoq(`oHoyOif37@f(05+9`o7lZH6qqedTM~1Z z_7qxX2wb%kl7gaY|NPi`8BC>zRH*cuIpT+Ne4iFd{$n_t0B9{->ScR=#<3@hTg|-pMNQY3HDMkJd@T6%$j-Ofirc~|Oa6Km@tbX%bvmupS zL{avGs2Fo4n{uv4E!DvO#_a#6+uM!*|UG zjbcHPmUz|qVLOH+!G$c2&gn{^nqHVqw+jfukD`Tucosu_T9DDlV#m(D3IWG9hnLPs z^1zcu(FM;5M;7@Ul)zlkdQqCk3c2JWm5$owD;d+c6)AYR`p>FJlW8E`-o6(lq3|&6 zYTtc%O0I_?lJMDA%WD;Mfn38H(6uJTw@+~}14+BPOL{%8>CsANp*XStW(r3=!Wp`S z1vwUGcu;2D1BiK!nPD997`r7NmZ_YzhyB{6CCFjn#&Iu1FXQ~9x#i!5y zAx!7tu&n%x%KC<9aR9O$+p3Rb*N$#>)j9q)1PaR@+F_{f(TdqyCHnUEz}-}bjbdG-d1IuZr+b?|L>S7FzVaa-m`DII2*-STJiqsO(h9OUT!`%(W7=0Ji>|+ zuu&O`Nk7NGuU~EnM~2OGYgxE;0>|vF5&~HJr9!boHelGdFFX)?=ITODy91fDWyPTe zQ^2sVIv78CMPMYy?5(oMtdDTozk+}P+up;`=ecnjr*);dV=2}5C4s#S)p>L(@;4;i zNvW8M2mfu)_Up}@=W=9l(sBpGsx=(j{wfRYz`VQfg?$BHCPw!-{@MmQEu~^Ayo|fm zyqoDM99*sQ-MQ|cnlm_NZxs}m8*xG(Jw$3hJ4DX#7!4@WR!(v5Qs*bW-uG%O9Dh}E z&@Zq96ul^2#h)uNeB9|u&tMq0Ub~T0!)_VJw!eyN;`!m{#1SKa-Jw@EIu#uUq6?%{ zRIbC<(ckO5dJZVj{#^MAc zPesn~Je1~q6Acc|l#_rZ)WkxZDXJ~_qm{`^_zRcd!a+*(&msk`(6{ms--4l=^n8Ja zpsXJ$(Ns~IK(;Yw3_K(kYz_-@W6AB=+%33I(C?a~J~s3NoQ6v#I0qb=rVG-not0+h z_|iK*J%Vdr&Ax0-%S?Np9Ze06O!EWM#Mqe?p9Q+^U)`y2GQ809;%4_o#qqk7hEEL+ z(yV}8eT&6EP{5FxtHW?$K^AddyWRQ@=g5dEop$HB0V!zOkGGcmR_RUu_if<&uDcq# zRD02t(|){l)x;^m?hX3GDSY_1O;JnrR8wfP^v+Kg+7;DHuj^NP51jWABB3h{i=0o@ zgAd6`Z=dCaBX`9OyHa25$~N>=uprJ+Ugp-05ZUxf`D&V$grBW{hd4H>&%?g)n;6S) zfQ{&via&qdY64EFvxuU6&DKzRz9sQ)EAWZDzC0Ul+f(TZT^-!TW|i;Oemr!kv`_jt z_@v94{gq%_5xktH$j+r*)4R2nrKX z&ppr1zHm=a;!OEm@g0vj&5f&}r45U=A6|BFn!?#(Y^kFtWCcHu`=-+GHjMz+EqCs3 z6W+xGXBwIs942JGJCGBcfH3HblN|^d3vzDp`;v{vM1gBsdxmL;!{qFQtih3Kh9S-O zS!r$`^;1|&KzW3iVHKYLJp*WBmIDl&GAc)O-HO=G>j?XR%6Gqee2wOWt|E%^Xz?HG z6Vo^yplq}}^jvx=S{4ue_OH+l@oniBf5p%KF1#B0w86G+5Vd|sIdw~Ue>jVu+RJ-h(d(H0(U^8cMN@nx z^C;XjihWVNJ*tcwyj$%T8TV<*pa;NnOYE1LrUpl*Nre$4%0Y=RrXDnX0Y|3kkAw}Brt0&e9_J#fe3}EkduVi@UJuU0YvWctpQq}R6TVEJIwrixGd&&+ z1ely#l|N%jA@Bt{e!JUdXF7bbz>2;f;@hb9IE!swoNlrU9_45FR_Fl~-7*!pvUGuh Zj6AmZ;$hcH@SJ#i?}yQw8gTXN{~tsXjobhL literal 0 HcmV?d00001 diff --git a/train_singlegpu.py b/train_singlegpu.py new file mode 100644 index 0000000..4d028eb --- /dev/null +++ b/train_singlegpu.py @@ -0,0 +1,97 @@ +import norch +import norch.nn as nn +import norch.optim as optim +from norch.norchvision import transforms as T +import random +random.seed(1) +from memory_profiler import profile + +@profile +def main(): + + + BATCH_SIZE = 32 + device = "cpu" + epochs = 10 + + transform = T.Compose( + [ + T.ToTensor(), + T.Reshape([-1, 784, 1]) + ] + ) + + target_transform = T.Compose( + [ + T.ToTensor() + ] + ) + + + print("Loading data") + train_data, test_data = norch.norchvision.datasets.MNIST.splits(transform=transform, target_transform=target_transform) + train_loader = norch.utils.data.DataLoader(train_data, batch_size=BATCH_SIZE) + + class MyModel(nn.Module): + def __init__(self): + super(MyModel, self).__init__() + self.fc1 = nn.Linear(784, 30) + self.sigmoid1 = nn.Sigmoid() + self.fc2 = nn.Linear(30, 10) + self.sigmoid2 = nn.Sigmoid() + + def forward(self, x): + out = self.fc1(x) + out = self.sigmoid1(out) + out = self.fc2(out) + out = self.sigmoid2(out) + + return out + + print("Creating model") + model = MyModel().to(device) + criterion = nn.CrossEntropyLoss() + optimizer = optim.SGD(model.parameters(), lr=0.01) + loss_list = [] + + print("Starting training") + for epoch in range(epochs): + + avg_loss = 0 + num_steps = 0 + + for idx, batch in enumerate(train_loader): + + if idx % 100 == 0 and idx > 0: + print(f"Epoch: {epoch}/{epochs} - Step: {idx} / {len(train_loader)}") + break + + inputs, target = batch + + inputs = inputs.to(device) + target = target.to(device) + + outputs = model(inputs) + loss = criterion(outputs, target) + + optimizer.zero_grad() + + loss.backward() + + optimizer.step() + + avg_loss += loss[0] + num_steps += 1 + + avg_loss = avg_loss / num_steps + print(f'Epoch [{epoch + 1}/{epochs}], Loss: {avg_loss:.4f}') + loss_list.append(avg_loss) + + break + + + +if __name__ == "__main__": + main() + +