Skip to content

Instantly share code, notes, and snippets.

@algal
Created December 20, 2024 06:46
Show Gist options
  • Save algal/b1ba21105df4f118a6b2c3722b4355ce to your computer and use it in GitHub Desktop.
Save algal/b1ba21105df4f118a6b2c3722b4355ce to your computer and use it in GitHub Desktop.
Shuffling in torch vs numpy-public.ipynb
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {},
"id": "3631be3b",
"cell_type": "markdown",
"source": "# Torch vs Numpy shuffling\n\nThe purpose of this notebook is\n\n1. to confirm Oskar's analysis of problems with `torch.randperm`.\n\n2. to show that it can be fixed by using numpy's default random number generator or the PCG64DXSM generator specifically.\n\n\nOskar's analysis implied that `torch.randperm` was not shuffling elements uniformly when the number of elements became very large, e.g., a billion or more ([discord link](https://discord.com/channels/1200111522916094103/1276053252571533313/1278328850803064865)). We confirmed this in the notebook below.\n\nSpecifically, this notebook confirms the following: If you start with 3 billion elements, tag them as belonging to ten \"deciles\" representing the first 10% of elements, the second 10% of elements, and so on, then shuffle all the elements, and then look at the first 10,000 elements, you do not find that the ten deciles are approximately uniformly distributed among the first 10,000 elements. Instead, `torch.randperm` is more likely to put the earlier elements (the lower deciles) into the first 10,000 elements of the shuffled collection. This corresponds to the bottom-left figure in Oskar's original post.\n\nWe then found that switching to numpy's random number generator, or to numpy's PCG64DXSM generator, resolves this issue, and seems to produces an approximately uniform distribution of deciles within the first 10,000 elements of the shuffled collection..\n\nWe noticed that OLMo encountered a similar issue and resolved it by using a specific numpy generator ([OLMo link](https://discord.com/channels/1200111522916094103/1276053252571533313/1278402521391562752) ).\n"
},
{
"metadata": {},
"id": "48ff4441",
"cell_type": "markdown",
"source": "## How uniform is torch's shuffling with randperm?"
},
{
"metadata": {
"trusted": false
},
"id": "816fad78",
"cell_type": "markdown",
"source": "Let's generate an array representing a shuffling of the integers from 0 to (3 * 10^9 - 1)"
},
{
"metadata": {
"trusted": true
},
"id": "cd483264",
"cell_type": "code",
"source": "import torch\n\nshuffled = torch.randperm(3 * 10**9)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": false
},
"id": "76553ee0",
"cell_type": "code",
"source": "shuffled_interval = shuffled[:10_000]",
"execution_count": 2,
"outputs": []
},
{
"metadata": {
"trusted": false
},
"id": "f7042107",
"cell_type": "code",
"source": "shuffled_interval[:50]",
"execution_count": 3,
"outputs": [
{
"data": {
"text/plain": "tensor([1994940797, 2347954103, 1691579500, 262720464, 2748298413, 2222743612,\n 1653995, 2342555504, 1440586107, 1077345365, 668539175, 2788525165,\n 117518658, 699722858, 1290958150, 2665873790, 2552246067, 2283160201,\n 177004620, 31564517, 2704208229, 1047164862, 25139448, 2216018010,\n 1004277474, 2440298876, 1240531966, 326584590, 943397255, 34365751,\n 150611451, 129402432, 2867900352, 1395077156, 256310869, 1292414480,\n 209935101, 440610241, 848544906, 407409817, 2578392564, 1809067203,\n 1297671095, 1108743574, 1086617589, 1632128034, 681494780, 1207082789,\n 1001392368, 879276196])"
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": false
},
"id": "e776543d",
"cell_type": "code",
"source": "[x.item() for x in shuffled_interval[:10]]",
"execution_count": 4,
"outputs": [
{
"data": {
"text/plain": "[1994940797,\n 2347954103,\n 1691579500,\n 262720464,\n 2748298413,\n 2222743612,\n 1653995,\n 2342555504,\n 1440586107,\n 1077345365]"
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": false
},
"id": "c97d3956",
"cell_type": "code",
"source": "shuffled.shape[0]",
"execution_count": 5,
"outputs": [
{
"data": {
"text/plain": "3000000000"
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {},
"id": "82671979",
"cell_type": "markdown",
"source": "Define a decile function, which tells us which of the ten \"decile\" bins an element belonged to. That is, in the original unshuffled collection, was it in the first 10%, the second 10%, ... and so on."
},
{
"metadata": {
"trusted": false
},
"id": "d8528af6",
"cell_type": "code",
"source": "def decile(index, collection_size):\n \"Returns 1 to 10, for the decile of `index` within `collection_size`\"\n return 1 + int(index // (collection_size / 10))",
"execution_count": 6,
"outputs": []
},
{
"metadata": {},
"id": "525e11ae",
"cell_type": "markdown",
"source": "Verify the above function works as expected:"
},
{
"metadata": {
"trusted": false
},
"id": "6e6ec9cd",
"cell_type": "code",
"source": "n = 20\n[decile(x,n) for x in range(n)]",
"execution_count": 7,
"outputs": [
{
"data": {
"text/plain": "[1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10]"
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": false
},
"id": "bde78acd",
"cell_type": "code",
"source": "del n",
"execution_count": 8,
"outputs": []
},
{
"metadata": {},
"id": "de916fa2",
"cell_type": "markdown",
"source": "Compute the deciles for the first 10,000 shuffled values"
},
{
"metadata": {
"trusted": false
},
"id": "ba80ed86",
"cell_type": "code",
"source": "deciles = [decile(x.item(),shuffled.shape[0]) for x in shuffled_interval]",
"execution_count": 9,
"outputs": []
},
{
"metadata": {
"trusted": false
},
"id": "4845849e",
"cell_type": "markdown",
"source": "Let's graph a histogram of the values in deciles."
},
{
"metadata": {
"trusted": false
},
"id": "d983a9eb",
"cell_type": "code",
"source": "%matplotlib inline\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(10, 6))\nplt.hist(deciles, bins=range(1, 12), align='left', rwidth=0.8)\nplt.xlabel('Decile')\nplt.ylabel('Frequency')\nplt.title('Histogram of Deciles, with torch.randperm')\nplt.xticks(range(1, 11))\nplt.show()",
"execution_count": 11,
"outputs": [
{
"data": {
"image/png": "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CggIKNbm4eFR5rBYlvfLpX1//fVXubi4KDg4+IrHu976S6pz1apV6t+/v2699VYtXbpU27ZtU0pKioYNG1bi78qVasjKylJRUVGJ53O5cyyt78Vr/Msvv+jzzz8v9t68+Lzfxfdmaed6UUn/Nnh7e9uFw4vtpf17AaD88cwWgArJ1dVV48aN07hx43Tq1Clt2LBBL774ou69914dO3as1BnRLn64Sk9PL/ah/sSJE+bzWhf7lfRcRkZGRomjWyV9587SpUsVERGhuXPn2rWfPn269JMsB78/10udOHFCVapUUY0aNcr9uDt27FBGRoaGDx8uSapRo4ZcXFw0aNCgy454hIWFSZJuueWWYhOVlMXFn+OkSZMu+4xKw4YNJUk+Pj6aOnWqpk6dql9++cUc5erTp4/dpBxXKzIyUomJidqxY4e+/fZbvfTSS5Kkrl27KikpSUeOHFHVqlWdbvbBsrxfLn3P33LLLSosLFRGRkapAaE8XO73LSwsTCtXrrRbn5eXV6Zj1KhRQzabTRkZGcXWldR2ufaLbRevcc2aNdWiRQu9+uqrJe7j4h8qLuL7vICKiZEtABVe9erV9dBDD2n06NE6efKk+RD+xWmRL/0redeuXSX99qHs91JSUrR//35FRkZKktq3by8PDw+tXLnSrt/27duv6VYcm81WbIrm77//vtjsblZo2LChbr31Vi1btszutr6zZ8/qk08+MWecK08nT57UU089JTc3Nz377LOSJG9vb3Xp0kXfffedWrRoUeKI5sUPob169dIPP/ygr7766rrqaNiwocLDw7V79+4Sj9euXTu728cuCgoK0tChQ/XHP/5RBw4cKNNtlpGRkbLZbHr55ZdVpUoVc7KHbt26KTk5WUlJSbrnnnsue1vYRZd7D1+vy+23PN4vF29du/SPCzfKxS/Z/n04ycjIKHE2wqvh4+OjO++8U6tWrbIbFTp9+rQ5k+SlNm7caPdHmsLCQq1cuVL169c3/8ATFRWlvXv3qn79+iW+Ny8NWwAqJka2AFRIffr0UbNmzdSuXTvdcsstOnLkiGbPnq26desqPDxckszvd3rrrbc0ZMgQubm5qWHDhmrYsKFGjBihhIQEValSRb169TJnIwwNDTUDwsUplOPi4lSjRg09+OCDOn78uKZOnapatWrZPdNSmqioKL3yyiuaMmWKOnfurAMH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ffRReXl5lXeNAAAAAFDhlClsSZKXl5eGDRtmTsMOAAAAAPifMoWtDz74oNT1gwcPLlMxAAAAAHCzKPP3bP1eQUGBzp07J3d3d3l7exO2AAAAAFR6ZZqNMCsry245c+aMDhw4oE6dOjFBBgAAAACojGGrJOHh4XrttdeKjXoBAAAAQGVUbmFLklxcXHTixIny3CUAAAAAVEhlemZrzZo1dq8Nw1B6errmzJmju+++u1wKAwAAAICKrExh64EHHrB7bbPZdMstt6hr16568803y6MuAAAAAKjQyhS2ioqKyrsOAAAAALiplOszWwAAAACA35RpZGvcuHFX3XfmzJllOQQAAAAAVGhlClvfffeddu3apQsXLqhhw4aSpB9++EEuLi5q06aN2c9ms5VPlQAAAABQwZQpbPXp00e+vr5avHixatSoIem3Lzp+/PHH9Yc//EHjx48v1yIBAAAAoKIp0zNbb775puLi4sygJUk1atTQ9OnTmY0QAAAAAFTGsJWTk6NffvmlWHtmZqZOnz593UUBAAAAQEVXprD14IMP6vHHH9fHH3+s48eP6/jx4/r44481fPhw9evXr7xrBAAAAIAKp0zPbM2bN08TJkzQY489poKCgt925Oqq4cOHa8aMGeVaIAAAAIDS1Zv4d0eXcEMcfq23o0u4JmUKW97e3nrnnXc0Y8YM/fTTTzIMQ7fffrt8fHzKuz4AAAAAqJDKFLYuSk9PV3p6uu655x55eXnJMAymewcAACXiL+8AKpsyPbP13//+V5GRkWrQoIHuu+8+paenS5KeeOIJpn0HAAAAAJVxZOvZZ5+Vm5ubjh49qsaNG5vtAwYM0LPPPsv07wCASomRGwDA75UpbH355Zdav369ateubdceHh6uI0eOlEthAAAAlQlhHbj5lOk2wrNnz8rb27tY+3/+8x95eHhcd1EAAAAAUNGVKWzdc889+uCDD8zXNptNRUVFmjFjhrp06VJuxQEAAABARVWm2whnzJihiIgI7dy5U/n5+Xr++ee1b98+nTx5Ut9880151wgAAAAAFU6ZRraaNGmi77//Xnfeeae6d++us2fPql+/fvruu+9Uv3798q4RAAAAACqcax7ZKigoUI8ePTR//nxNnTrVipoAAAAAoMK75pEtNzc37d27ly8vBgAAAIBSlOk2wsGDBysxMbG8awEAAACAm0aZ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s8+qY8eOio2NVf/+/bVjxw4tWLBACxYscHRpTqOoqEgLFy7UkCFD5OrKx53f69Onj1599VXVqVNHTZs21XfffaeZM2dq2LBhji7NKaxfv16GYahhw4Y6ePCgnnvuOTVs2FCPP/64o0u74a70OTA6OlqxsbEKDw9XeHi4YmNj5e3trYEDBzqwaifj0LkQ4fSSk5MNScWWIUOGOLo0hyvpukgyFi5c6OjSnMKwYcOMunXrGu7u7sYtt9xiREZGGl9++aWjy3JqTP3+PwMGDDBq1apluLm5GSEhIUa/fv2Mffv2Obosp/L5558bzZo1Mzw8PIxGjRoZCxYscHRJTmX9+vWGJOPAgQOOLsXp5OTkGGPHjjXq1KljeHp6GrfddpsxefJkIy8vz9GlOYWVK1cat912m+Hu7m4EBwcbo0ePNk6dOuXoshziSp8Di4qKjClTphjBwcGGh4eHcc899xh79uxxbNFOxmYYhnHDEx4AAAAA3OR4ZgsAAAAALEDYAgAAAAALELYAAAAAwAKELQAAAACwAGELAAAAACxA2AIAAAAACxC2AAAAAMAChC0AAAAAsABhCwCAclCvXj3Nnj3bfG2z2fTpp586rB4AgOMRtgAAN7WhQ4fKZrPJZrPJzc1NQUFB6t69u95//30VFRWV23FSUlI0YsSIctsfAKDiI2wBAG56PXv2VHp6ug4fPqy1a9eqS5cuGjt2rKKionThwoVyOcYtt9wib2/vctkXAODmQNgCANz0PDw8FBwcrFtvvVVt2rTRiy++qM8++0xr167VokWLJEnZ2dkaMWKEAgMDVa1aNXXt2lW7d++228+aNWvUrl07eXp6qmbNmurXr5+57tLbCC/1888/a8CAAapRo4YCAgJ0//336/DhwxacLQDAWRC2AACVUteuXdWyZUutWrVKhmGod+/eysjI0BdffKHU1FS1adNGkZGROnnypCTp73//u/r166fevXvru+++08aNG9WuXburOta5c+fUpUsXVa1aVZs3b9aWLVtUtWpV9ezZU/n5+VaeJgDAgVwdXQAAAI7SqFEjff/990pOTtaePXuUmZkpDw8PSdIbb7yhTz/9VB9//LFGjBihV199VY888oimTp1qbt+yZcurOs6KFStUpUoVvffee7LZbJKkhQsXqnr16vr666/Vo0eP8j85AIDDEbYAAJWWYRiy2WxKTU3VmTNnFBAQYLc+NzdXP/30kyQpLS1NTz75ZJmOk5qaqoMHD8rX19eu/fz58+b+AQA3H8IWAKDS2r9/v8LCwlRUVKRatWrp66+/LtanevXqkiQvL68yH6eoqEht27bVhx9+WGzdLbfcUub9AgCcG2ELAFApffXVV9qzZ4+effZZ1a5dWxkZGXJ1dVW9evVK7N+iRQtt3LhRjz/++DUfq02bNlq5cqU5+QYAoHJgggwAwE0vLy9PGRkZ+vnnn7Vr1y7Fxsbq/vvvV1RUlAYPHqxu3bqpQ4cOeuCBB7R+/XodPnxYW7du1UsvvaSdO3dKkqZMmaLly5drypQp2r9/v/bs2aP4+PirOv6jjz6qmjVr6v7779c//vEPHTp0SJs2bdLYsWN1/PhxK08dAOBAhC0AwE1v3bp1qlWrlurVq6eePXsqOTlZb7/9tj777DO5uLjIZrPpiy++0D333KNhw4apQYMGeuSRR3T48GEFBQVJkiIiIvTRRx9pzZo1atWqlbp27apvv/32qo7v7e2tzZs3q06dOurXr58aN26sYcOGKTc3l5EuALiJ2QzDMBxdBAAAAADcbBjZAgAAAAALELYAAAAAwAKELQAAAACwAGELAAAAACxA2AIAAAAACxC2AAAAAMAChC0AAAAAsABhCwAAAAAsQNgCAAAAAAsQtgAAAADAAoQtAAAAALDA/wPVeGIKVpdjoQAAAABJRU5ErkJggg==",
"text/plain": "<Figure size 1000x600 with 1 Axes>"
},
"metadata": {},
"output_type": "display_data"
}
]
},
{
"metadata": {},
"id": "cd811ebd",
"cell_type": "markdown",
"source": "The above shows that torch's shuffler is not producing a uniform shuffle over a collection of 3 B elements."
},
{
"metadata": {},
"id": "ac04d4fe",
"cell_type": "markdown",
"source": "## Now let's try numpy with the PCG64DXSM generator."
},
{
"metadata": {
"trusted": false
},
"id": "da392490",
"cell_type": "markdown",
"source": "Let's generate an array representing a shuffling of the integers from 0 to (3 * 10^9 - 1), but using this random number generator from numpy: numpy.random.PCG64DXSM"
},
{
"metadata": {
"trusted": false
},
"id": "359b2270",
"cell_type": "code",
"source": "import numpy as np\n\nrng = np.random.Generator(np.random.PCG64DXSM())\nshuffled = rng.permutation(3 * 10**9)\nshuffled = torch.from_numpy(shuffled)\nshuffled_interval = shuffled[:10_000]",
"execution_count": 12,
"outputs": []
},
{
"metadata": {
"trusted": false
},
"id": "12e73269",
"cell_type": "code",
"source": "deciles = [decile(x.item(),shuffled.shape[0]) for x in shuffled_interval]",
"execution_count": 13,
"outputs": []
},
{
"metadata": {
"trusted": false
},
"id": "c1e19f7c",
"cell_type": "code",
"source": "%matplotlib inline\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(10, 6))\nplt.hist(deciles, bins=range(1, 12), align='left', rwidth=0.8)\nplt.xlabel('Decile')\nplt.ylabel('Frequency')\nplt.title('Histogram of Deciles with PCG64DXSM randomization')\nplt.xticks(range(1, 11))\nplt.show()",
"execution_count": 14,
"outputs": [
{
"data": {
"image/png": "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/GGaNm1qf29yc3MzERERZvTo0SY9Pd2hb/Y0wuy6wsPDjTHG7N2710gy69evNwkJCTc0jbAg31Pq1KljLl++bG//7rvvjCSzYMECY8z/vU80aNDAZGVl2fsdOnTIuLm5OfysTp482UgyH3/8sUMNb731lpFkVq5caW+TZIKCgsyZM2fsbUuXLjWSzN133+1wrOz3uT9PPb7eFMZvvvnGeHp6mh49ejjs688yMzPNpUuXzGuvvWb8/f0d+uU1jTD7uv353+i+++4zAQEBDv/mly9fNrVr1zYVK1a07/dWf1+BwoaRLaAImzNnjhISEnI8sqezXcu9996rXbt2qX///vrqq6+UlpZ2w8ddt26dJOVY3fDee+9VzZo1tWbNGknSli1blJGRoYceesih33333ZfnCln/+Mc/cm2fPHmyGjRoIE9PT7m6usrNzU1r1qzRvn37cvRt3769w/SkmjVrSlKOm7Wz248cOZLHmUr79+/XiRMn9Oijjzrss2TJkvrHP/6hLVu25Lkwwa0yf/oL9YULF7RmzRp16dJF3t7eDiOZ7du314ULF+zTmpYvX67q1aurZcuWt3T8X375RT/99JN69OghSTmOmZiYqP3790u68m+/fPlyvfTSS1q/fr3Onz9/Q8eIiorS+fPntWnTJklXRrBatWqlli1batWqVfY2Sbd8PlePItWtW1eSbnjlx6CgILm5uals2bLq2bOnGjRooBUrVsjT0/OW6vqznTt3ys3NzeGRPVKcvfKfu7u7li9fro4dO6pDhw764osvFBwc7DDq8N1332n8+PGaMmWKvLy8bqkmc42Rkl27dmndunUqUaKENmzYoIsXL+bo4+/vr2+++UYJCQkaM2aMOnfurAMHDmj48OGqU6dOrisuSlemEm7btk27d+/W9OnTdccdd+j++++/6foL4j2lQ4cODtMwr/7ZyX6f6N69u8Poa5UqVRQREeGwr7Vr18rHx0f//Oc/Hdqz30+z3z+zNW/eXD4+Pvbn2e9b7dq1czhWdvuN/jzv27dPnTp1UkREhGbMmOGwr7Vr16ply5YqXbq0XFxc5Obmpn/96186efLkDU+9/rOzZ89q69at+uc//6mSJUva211cXPToo4/q2LFj9veSbLf6+woUFoQtoAirWbOmwsPDczxKly593dcOHz5cb7/9trZs2aJ27drJ399fUVFRN7Q8dvbUsODg4BzbQkJC7Nuz/zcwMDBHv9za8trnuHHj9PTTT6tRo0b69NNPtWXLFiUkJKht27a5fqj38/NzeO7u7n7N9gsXLuRay5/PIa9zzcrKUkpKSp6vvxVHjhyxryB38uRJXb58WRMmTMjxYbx9+/aSZP/Q+vvvv6tixYq3fPzffvtNkjRs2LAcx+zfv7/DMd9//329+OKLWrp0qZo3by4/Pz898MAD11yOXJIiIiLk7e2t1atX65dfftGhQ4fsYWvr1q06c+aMVq9erWrVqik0NPSWzsff39/hefZ9VTcaDFevXq2EhATt3LlTf/zxhzZu3Ki77rpL0pUV+ry9vXXw4MEb2lflypUl5fzgWKNGDfsfTf58v9af64+IiLCv9CdduberWbNm2rFjh72td+/e6tq1q8LDw3X69GmdPn3a/nOelpbmsCz79WTXePVqhpcuXVJMTIxCQkK0ePFi7dmzxyHwXS08PFwvvviiPvnkE504cULPPfecDh06pPj4+Fz733///QoLC9OUKVM0d+5c9e7dO89ppNdSEO8p1/vZyX6fCAoKyvHaq9tOnjypoKCgHOcSEBAgV1fXHFNvC/L9LNuJEyfUtm1bVaxYUYsXL7a/VroS1Fu3bi3pyuqa3377rRISEjRixAiHc74ZKSkpMsbk+T4qKcd53+rvK1BY5LxbFUCx4OrqqiFDhmjIkCE6ffq0Vq9erZdffllt2rTR0aNHc9x38WfZ/xFMTEzM8aH+xIkTKleunEO/7A/tf5aUlJTr6FZuH6bmzZunyMhITZo0yaH9Zj4w5tefz/VqJ06cUIkSJVS2bNkCP+53332npKQk+1LhZcuWtf8VeMCAAbm+JjuMlC9fPsdCJfmR/e84fPjwXO8lka6EA0ny8fHRqFGjNGrUKP3222/2Ua6OHTs6LMpxNXd3dzVt2lSrV69WxYoVFRQUpDp16tgXgFi/fr3WrFmj6OjoWz6fW1WvXj37Nbmai4uLoqKitHz5ch07duy6YTcyMlKurq5atmyZnnjiCXt79gII0pV7df4s+y/7uTHGOIy87t27V3v37tUnn3ySo+8dd9yhevXq5fkdcFdbtmyZveY/e+211/TDDz/Y76d76qmnNGbMGHXp0uW694i5ublp5MiRevfdd7Vnz548+z3++ON65ZVXZLPZFBMTc0P1Xu2veE/Jfp9ISkrKse3qNn9/f23dulXGGIfakpOTdfny5Tx/xgpKWlqa2rdvr6ysLP33v//N8ce5hQsXys3NTV988YXDqO2tfK1C2bJlVaJEiTzfRyVZft6AszCyBUBlypTRP//5Tw0YMECnTp3SoUOHJOX9l8QWLVpIuvKB5c8SEhK0b98+RUVFSZIaNWokDw+PHDc/b9my5aamgthsthyru/3www8OqwFapUaNGqpQoYLmz5/vMJ3q7Nmz+vTTT+0rFBakU6dO6amnnpKbm5uee+45SVdGL5o3b67vv/9edevWzXVEM/sDX7t27XTgwIFcv6foZtSoUUNhYWHatWtXrscLDw93GGHJFhgYqF69eumRRx7R/v37rzvNsmXLltq+fbs+/fRT+1RBHx8f3XfffZowYYJOnDhxQ1MIPTw8nPpX7+HDh8sYo379+uU6ne7SpUv6/PPPJV0Zbendu7e+/PJL+yp71xMcHKzGjRvr22+/dZj2e+7cOW3YsMG+OqJ0Zarv1Y/ssLJ06VJNmzbtho65atUqTZs2TREREQ7Tk7dt26YxY8aof//+9veD+Ph4VaxYUb169XI4/7wWZcmernet7/+KiYlRx44d9fzzz6tChQo3VPONKOj3lBo1aig4OFgLFixweJ84fPiwfYpstqioKJ05cyZHeMleuTD7/dMKFy9eVJcuXXTo0CEtX7481z8K2Gw2ubq6OkybPH/+vObOnZuj743+zvn4+KhRo0ZavHixQ//sL/WuWLHidb+TECiqGNkCiqmOHTuqdu3aCg8PV/ny5XX48GGNHz9eVapUUVhYmCSpTp06kqT33ntPMTExcnNzU40aNVSjRg098cQTmjBhgkqUKKF27drp0KFDevXVV1WpUiV7QPDz89OQIUM0evRolS1bVl26dNGxY8c0atQoBQcH57ns89Wio6P1+uuva+TIkWrWrJn279+v1157TaGhoQ7Lg1uhRIkSio+PV48ePRQdHa0nn3xSGRkZGjt2rE6fPp1jmeub9fPPP2vLli3KysrSyZMntXXrVk2fPl1paWmaM2eOwwph7733npo2baq///3vevrpp1W1alWlp6frl19+0eeff24PV4MHD9aiRYvUuXNnvfTSS7r33nt1/vx5bdiwQdHR0WrevPkN1zdlyhS1a9dObdq0Ua9evVShQgWdOnVK+/bt044dO+wjJ40aNVJ0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GHPdPjabTbGxsYqNjc2zj6enpyZMmKAJEyYUYHUAAAAAkLdCfc8WAAAAABRVhC0AAAAAsABhCwAAAAAsQNgCAAAAAAsQtgAAAADAAoQtAAAAALAAYQsAAAAALEDYAgAAAAALELYAAAAAwAKELQAAAACwAGELAAAAACxA2AIAAAAACxC2AAAAAMAChC0AAAAAsABhCwAAAAAsQNgCAAAAAAsQtgAAAADAAoQtAAAAALAAYQsAAAAALEDYAgAAAAALELYAAAAAwAKELQAAAACwAGELAAAAACxA2AIAAAAACxC2AAAAAMAChC0AAAAAsABhCwAAAAAsQNgCAAAAAAsQtgAAAADAAoQtAAAAALAAYQsAAAAALEDYAgAAAAALELYAAAAAwAKELQAAAACwAGELAAAAACxA2AIAAAAACxC2AAAAAMAChC0AAAAAsABhCwAAAAAsQNgCAAAAAAsQtgAAAADAAoQtAAAAALAAYQsAAAAALEDYAgAAAAALELYAAAAAwAKELQAAAACwAGELAAAAACxA2AIAAAAACxC2AAAAAMAChC0AAAAAsABhCwAAAAAsQNgCAAAAAAsQtgAAAADAAoQtAAAAALAAYQsAAAAALEDYAgAAAAALELYAAAAAwAKELQAAAACwAGELAAAAACxA2AIAAAAACxC2AAAAAMAChC0AAAAAsABhCwAAAAAsQNgCAAAAAAsQtgAAAADAAoQtAAAAALAAYQsAAAAALEDYAgAAAAALELYAAAAAwAKELQAAAACwAGELAAAAACxA2AIAAAAACxC2AAAAAMAChC0AAAAAsECxClsffvihQkND5enpqYYNG+qbb75xdkkAAAAAblPFJmwtWrRIgwcP1ogRI/T999/r73//u9q1a6cjR444uzQAAAAAt6FiE7bGjRunPn36qG/fvqpZs6bGjx+vSpUqadKkSc4uDQAAAMBtyNXZBfwVLl68qO3bt+ull15yaG/durU2bdqU62syMjKUkZFhf56amipJSktLs67Qm5CVcc7ZJfwl8nu9i8P1uZWfRa7PtXF9ro3rk7ficG0krs/1cH2ujetzbVyfayssn8Wz6zDGXLOfzVyvx23gxIkTqlChgr799ltFRETY2+Pi4jR79mzt378/x2tiY2M1atSov7JMAAAAAEXI0aNHVbFixTy3F4uRrWw2m83huTEmR1u24cOH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XSD7AgDcHghbAIDbnoeHh4KCglShQgU1aNBAL7/8sj777DMtX75cs2bNkiSlpqbqiSeeUEBAgEqVKqUWLVpo165dDvtZtmyZwsPD5enpqXLlyqlr1672bVdPI7za8ePH9fDDD6ts2bLy9/dX586ddejQIQvOFgBQWBC2AADFUosWLVSvXj0tXrxYxhh16NBBSUlJ+u9//6vt27erQYMGioqK0qlTpyRJX375pbp27aoOHTro+++/15o1axQeHn5Dxzp37pyaN2+ukiVL6uuvv9bGjRtVsmRJtW3bVhcvXrTyNAEATuTq7AIAAHCWO++8Uz/88IPWrVun3bt3Kzk5WR4eHpKkt99+W0uXLtV//vMfPfHEE3rzzTfVrVs3jRo1yv76evXq3dBxFi5cqBIlSmjatGmy2WySpJkzZ6pMmTJav369WrduXfAnBwBwOsIWAKDYMsbIZrNp+/btOnPmjPz9/R22nz9/Xr/++qskaefOnerXr1++jrN9+3b98ssv8vX1dWi/cOGCff8AgNsPYQsAUGzt27dPoaGhysrKUnBwsNavX5+jT5kyZSRJXl5e+T5OVlaWGjZsqH//+985tpUvXz7f+wUAFG6ELQBAsbR27Vrt3r1bzz33nCpWrKikpCS5urqqatWqufavW7eu1qxZo8cff/ymj9WgQQMtWrTIvvgGAKB4YIEMAMBtLyMjQ0lJSTp+/Lh27NihuLg4de7cWdHR0XrsscfUsmVLNW7cWA888IC++uorHTp0SJs2bdIrr7yibdu2SZJGjhypBQsWaOTIkdq3b592796t+Pj4Gzp+jx49VK5cOXXu3FnffPONDh48qA0bNmjQoEE6duyYlacOAHAiwhYA4La3YsUKBQcHq2rVqmrbtq3WrVun999/X5999plcXFxks9n03//+V/fff7969+6t6tWrq1u3bjp06JACAwMlSZGRkfrkk0+0bNky3X333WrRooW2bt16Q8f39vbW119/rcqVK6tr166qWbOmevfurfPnzzPSBQC3MZsxxji7CAAAAAC43TCyBQAAAAAWIGwBAAAAgAUIWwAAAABgAcIWAAAAAFiAsAUAAAAAFiBsAQAAAIAFCFsAAAAAYAHCFgAAAABYgLAFAAAAABYgbAEAAACABQhbAAAAAGCB/weXF5MPGo/toAAAAABJRU5ErkJggg==",
"text/plain": "<Figure size 1000x600 with 1 Axes>"
},
"metadata": {},
"output_type": "display_data"
}
]
},
{
"metadata": {},
"id": "6c6ad989",
"cell_type": "markdown",
"source": "This is much closer to a uniform distribution."
},
{
"metadata": {},
"id": "3df62049",
"cell_type": "markdown",
"source": "## Now let's try with numpy's default randperm."
},
{
"metadata": {
"trusted": false
},
"id": "85f9db59",
"cell_type": "code",
"source": "import numpy as np\n\nrng = np.random.default_rng()\nshuffled = rng.permutation(3 * 10**9)\nshuffled = torch.from_numpy(shuffled)\nshuffled_interval = shuffled[:10_000]",
"execution_count": 15,
"outputs": []
},
{
"metadata": {
"trusted": false
},
"id": "02839455",
"cell_type": "code",
"source": "deciles = [decile(x.item(),shuffled.shape[0]) for x in shuffled_interval]",
"execution_count": 16,
"outputs": []
},
{
"metadata": {
"trusted": false
},
"id": "52b2a6b4",
"cell_type": "code",
"source": "%matplotlib inline\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(10, 6))\nplt.hist(deciles, bins=range(1, 12), align='left', rwidth=0.8)\nplt.xlabel('Decile')\nplt.ylabel('Frequency')\nplt.title('Histogram of Deciles with numpy default rng')\nplt.xticks(range(1, 11))\nplt.show()",
"execution_count": 17,
"outputs": [
{
"data": {
"image/png": "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2rFjh63tf//7nyIiIlSrVi29+eabCgoK0scff6zRo0frxx9/1OTJkyX9HCratGmj06dP64UXXlCrVq10+fJl7dixQ8nJyWrQoMFt17F161Y9+uijatWqlebOnStfX1+tXLlSffr00dWrV20feseOHaulS5dq2rRpat68ua5cuaIjR47op59+KnLblSpV0gMPPKDNmzfbPgRv2bJFVqtVmZmZ+uKLLxQRESFJ2rx5s9q3b1/kh9Pdu3erffv2ateune1y2ZvP/7Bhw9StWzctX75cZ8+e1XPPPaf+/fvrk08+ueV5yMnJUY8ePTR06FCNGzdOO3bs0CuvvCJfX1/95S9/ueX6RW0zJiZGTz/9tJ577jktX75cEydOVEZGhj744AO98MILqlGjhhITEzV48GA1btxYLVu2tNvG0KFD1bFjR9sxvfTSS4qMjNSXX36pypUra/jw4Xr11Vc1b948TZs2zbbexYsXtXLlSo0aNUoeHh5F1rho0SI9+eST6tmzp958802lp6crLi5OWVlZqlDh/75HzsvLU8+ePfXpp5/q+eefV0REhM6cOaPJkycrMjJSe/fulaenp3bv3q1XXnlFW7dutZ33/FHKb775Rn379lVoaKjc3d116NAhvfrqq/rqq6/03nvvlegc/9Kt3tOKkp2drR49emj48OGaMGGC3Xvuf/7zHyUlJWnq1KmqWLGiEhIS1KtXLx0/flx169aVJG3YsEExMTF65JFHtGrVKt24cUNvvPGGvv/++zs+JgC/YABAKVm4cKEhqdhH7dq17dapXbu2MWjQINtydHS0cf/99xe7nxkzZhiSjFOnTtm1Hzt2zJBkjBgxwq79888/NyQZL774omEYhnHx4kXDarUaffr0seu3e/duQ5LRtm1bW9vWrVsNScYjjzxyy+O/ceOGkZOTY0RFRRm9evWytZ86dcqQZDRr1szIzc21tc+aNcuQZPTo0cNuO7GxsYYkIz09vch95ebmGiEhIUaTJk3stpmZmWkEBAQYERERBY7h/fffv+Ux3E7fVq1aGZ6enrblzp07GzVq1ChQ76hRowwPDw/j4sWLhmEYxtSpUw1JxqZNm4qtQZIxefLkAjVt3brV1tagQQOjefPmRk5Ojt260dHRRnBwsO2cNG7c2HjssceK3V9hXnrpJcPT09O4fv26YRiGMWzYMOPRRx81mjZtakyZMsUwDMM4f/68IcmYP3++bb1BgwYVeI17e3vbvcbz5f97ufn1mpCQYEgykpOTi61x0KBBhiTjn//8p117165djfr169uWCzt/hvF/r8uFCxcW2OYHH3xga8vJyTGqVatmSDL2799va//pp58MFxcXY+zYsQWO6Zevf8MwjM8++8yQZEybNs1uXwEBAUZWVpat7fXXXzcqVKhQ4N/2L+W/9lu0aGHk5eXZ2k+fPm24ubnZnf8VK1YUOB7DMIykpCRDkvH3v//drh5vb+8i95u/75ycHGPJkiWGi4uL7bVtGAXfy/K1bdvW7j2lsPNe1HtaUfL/Tu+9916B5yQZgYGBRkZGhq0tJSXFqFChgjF9+nRb2wMPPGDUrFnT7vxnZmYa/v7+Bh8PgdLDZYQASt2SJUuUlJRU4JF/OVtxHnzwQR06dEgjRozQxx9/rIyMjNve79atWyWpwKU8Dz74oBo2bKgtW7ZI+vlSqKysLPXu3duu3+9+97siZzL7/e9/X2j73Llz1aJFC3l4eMjV1VVubm7asmWLjh07VqBv165d7b51b9iwoSSpW7dudv3y27/77rsijlQ6fvy4Lly4oAEDBthts2LFivr973+vPXv26OrVq0WufyeMX4xQXr9+XVu2bFGvXr3k5eWlGzdu2B5du3bV9evXtWfPHknS+vXrVa9ePXXo0OGO9n/y5El99dVX6tevnyQV2GdycrKOHz8u6ee//fr16zVhwgRt27ZN165du619REVF6dq1a9q1a5ekn0ewOnbsqA4dOmjTpk22Nkl3fDw9evSwW27atKkk3dbMjxaLRd27dy+w/p3MGmmxWNS1a1fbsqurq+69914FBwfb3WPp5+engICAQveV/7fJFxERodq1a9v+jUrSmDFjlJqaqvfff1/Sz6NQc+bMUbdu3YqdUTD/td+3b1+7EcXatWvbRhzzffTRR6pcubK6d+9u9zq5//77FRQUdFszXB44cEA9evSQv7+/XFxc5ObmpoEDByo3N1cnTpy45fpmKup9qV27dvLx8bEtBwYG2v2trly5or179+qxxx6Tu7u7rV/FihULvJ4A3BnCFoBS17BhQ4WHhxd4+Pr63nLdiRMn6o033tCePXvUpUsX+fv7Kyoq6ramx86/NCz/MpxfCgkJsT2f/7+BgYEF+hXWVtQ2Z86cqT//+c9q1aqVPvjgA+3Zs0dJSUl69NFHC/1Q7+fnZ7ec/yGnqPbi7lm51bHm5eUpLS2tyPXvxHfffaeQkBBbHTdu3FBiYqLc3NzsHvkf2H/88UdJP8+KWKNGjTvef/5lTuPHjy+wzxEjRtjt869//ateeOEFrV27Vu3atZOfn58ee+wxff3118XuIyIiQl5eXtq8ebNOnjyp06dP28LW559/rsuXL2vz5s2qW7euQkND7+h4/P397ZatVqsk3VYw9PLyKnC5ndVqveX9Tr92m+7u7gVep/nthe0rKCio0LZfXr7ZvHlzPfzww7Z7+z766COdPn36lhNU5G+jqH380vfff69Lly7J3d29wGslJSXF9jopynfffaeHH35Y58+f19tvv61PP/1USUlJtppvN7ybwcvLq8hLgm9+TUk/vy7y601LS5NhGL/qPRBAyXDPFgCn4urqqrFjx2rs2LG6dOmSNm/erBdffFGdO3fW2bNni51tK/8DRnJycoEP9RcuXLDdr5Xfr7B7E1JSUgr9Vr2we3KWLVumyMhIzZkzx649MzOz+IMsBb881ptduHBBFSpUUJUqVUp9v1988YVSUlI0dOhQSVKVKlXk4uKiAQMGaOTIkYWukx9GqlWrVmCikpLI/ztOnDhRMTExhfapX7++JMnb21tTpkzRlClT9P3339tGubp37243KcfN3N3d1aZNG23evFk1atRQUFCQmjRpYrvfZdu2bdqyZYuio6Pv+HjMlh+cfjlphqRbBo07kZKSUmjbvffea9c2evRoPf7449q/f79mz56tevXqqWPHjsVuO/+1X9Q+fil/0pENGzYUuq1fjv4UZu3atbpy5YpWr16t2rVr29oL+506Dw+PAudY+vk8579mS9OdTGJRpUoVWSyWIt8DAZQeRrYAOK3KlSvrD3/4g0aOHKmLFy/q9OnTkor+5r99+/aSfg5Bv5SUlKRjx47ZZutq1aqVrFarVq1aZddvz549v+ryK4vFYqsl35dffmk3G6BZ6tevr+rVq2v58uV2l/VduXJFH3zwgW2GwtJ08eJFPf3003Jzc9Ozzz4r6edv19u1a6cDBw6oadOmhY5o5n847tKli06cOHFbEz8Up379+goLC9OhQ4cK3V94eHihH6IDAwM1ePBg/fGPf9Tx48dveZllhw4dtG/fPn3wwQe2SwW9vb31u9/9TomJibpw4cJtXUL4yxEFR8j/8uDLL7+0a7/VBCx34ubfYtu1a5fOnDlTYNKYXr16qVatWho3bpw2b96sESNG3DJE1K9fX8HBwVqxYoXda//MmTO2yz7zRUdH66efflJubm6hr5P8UF6U/Fp++e/cMAy98847BfrWqVOnwDk+ceKE7ZLW4vya0czS4O3trfDwcK1du1bZ2dm29suXLxc6ayGAkmNkC4BT6d69uxo3bqzw8HBVq1ZNZ86c0axZs1S7dm2FhYVJku33nd5++20NGjRIbm5uql+/vurXr6+nnnpKiYmJqlChgrp06WKbjbBmzZq2gODn56exY8dq+vTpqlKlinr16qVz585pypQpCg4OtrsHqjjR0dF65ZVXNHnyZLVt21bHjx/X1KlTFRoaWuhsjKWpQoUKSkhIUL9+/RQdHa3hw4crKytLM2bM0KVLl2xTdZfU119/rT179igvL08//fSTPv/8cy1YsEAZGRlasmSJGjVqZOv79ttvq02bNnr44Yf15z//WXXq1FFmZqZOnjypf//737ZwFRsbq1WrVqlnz56aMGGCHnzwQV27dk3bt29XdHS02rVrd9v1zZs3T126dFHnzp01ePBgVa9eXRcvXtSxY8e0f/9+231ArVq1UnR0tJo2baoqVaro2LFjWrp06W2F0aioKOXm5mrLli12U5x36NBBkydPlsVisQX84jRp0kTbtm3Tv//9bwUHB8vHx+eWH/JLU1BQkDp06GB7vdeuXVtbtmzR6tWrTdvn3r17NWzYMD3++OM6e/asJk2apOrVq9su88zn4uKikSNH6oUXXpC3t3ehU6ffrEKFCnrllVc0bNgw9erVS3/605906dIlxcXFFbiM8IknntA//vEPde3aVWPGjNGDDz4oNzc3nTt3Tlu3blXPnj3Vq1evIvfVsWNHubu7649//KOef/55Xb9+XXPmzCn0Et0BAwaof//+GjFihH7/+9/rzJkzSkhIULVq1W55TEW9p91q5O1OTJ06Vd26dVPnzp01ZswY5ebmasaMGapYsaIuXrxo2n6Bcseh03MAuKvkz0SWlJRU6PPdunW75WyEb775phEREWFUrVrVcHd3N2rVqmUMHTrUOH36tN16EydONEJCQowKFSrYzbSWm5trvP7660a9evUMNzc3o2rVqkb//v2Ns2fP2q2fl5dnTJs2zahRo4bh7u5uNG3a1Pjo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7ZqioqK0aNEiubi4OOKwAAAAAJQDTh22fHx8NGvWLM2aNavIPhaLRXFxcYqLiyuyj4eHhxITE+1+DBkAAAAAzOTU92wBAAAAQFlF2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMEGJwtapU6dKuw4AAAAAuKuUKGzde++9ateunZYtW6br16+Xdk0AAAAAUOaVKGwdOnRIzZs317hx4xQUFKThw4friy++KO3aAAAAAKDMKlHYaty4sWbOnKnz589r4cKFSklJUZs2bdSoUSPNnDlTP/zwQ2nXCQAAAABlyh1NkOHq6qpevXrpn//8p15//XV98803Gj9+vGrUqKGBAwcqOTm5tOoEAAAAgDLljsLW3r17NWLECAUHB2vmzJkaP368vvnmG33yySc6f/68evbsWVp1AgAAAECZ4lqSlWbOnKmFCxfq+PHj6tq1q5YsWaKuXbuqQoWfs1toaKjmzZunBg0alGqxAAAAAFBWlChszZkzR0OGDNGTTz6poKCgQvvUqlVLCxYsuKPiAAAAAKCsKlHY+vrrr2/Zx93dXYMGDSrJ5gEAAACgzCvRPVsLFy7U+++/X6D9/fff1+LFi++4qF86f/68+vfvL39/f3l5een+++/Xvn37bM8bhqG4uDiFhITI09NTkZGROnr0qN02srKy9Mwzz6hq1ary9vZWjx49dO7cuVKtEwAAAAB+qURh67XXXlPVqlULtAcEBCg+Pv6Oi8qXlpamhx56SG5ublq/fr3+97//6c0331TlypVtfRISEjRz5kzNnj1bSUlJCgoKUseOHZWZmWnrExsbqzVr1mjlypXauXOnLl++rOjoaOXm5pZarQAAAADwSyW6jPDMmTMKDQ0t0F67dm199913d1xUvtdff101a9bUwoULbW116tSx/bdhGJo1a5YmTZqkmJgYSdLixYsVGBio5cuXa/jw4UpPT9eCBQu0dOlSdejQQZK0bNky1axZU5s3b1bnzp1LrV4AAAAAyFeika2AgAB9+eWXBdoPHTokf3//Oy4q37p16xQeHq7HH39cAQEBat68ud555x3b86dOnVJKSoo6depka7NarWrbtq127dolSdq3b59ycnLs+oSEhKhx48a2PoXJyspSRkaG3QMAAAAAbleJwtYTTzyh0aNHa+vWrcrNzVVubq4++eQTjRkzRk888USpFfftt99qzpw5CgsL08cff6ynn35ao0eP1pIlSyRJKSkpkqTAwEC79QIDA23PpaSkyN3dXVWqVCmyT2GmT58uX19f26NmzZqldlwAAAAA7n4luoxw2rRpOnPmjKKiouTq+vMm8vLyNHDgwFK9ZysvL0/h4eG2bTZv3lxHjx7VnDlzNHDgQFs/i8Vit55hGAXabnarPhMnTtTYsWNtyxkZGQQuAAAAALetRGHL3d1dq1at0iuvvKJDhw7J09NTTZo0Ue3atUu1uODgYN133312bQ0bNtQHH3wgSbbf+EpJSVFwcLCtT2pqqm20KygoSNnZ2UpLS7Mb3UpNTVVERESR+7ZarbJaraV2LAAAAADKlxJdRpivXr16evzxxxUdHV3qQUuSHnroIR0/ftyu7cSJE7Z9hYaGKigoSJs2bbI9n52dre3bt9uCVMuWLeXm5mbXJzk5WUeOHCk2bAEAAADAnSjRyFZubq4WLVqkLVu2KDU1VXl5eXbPf/LJJ6VS3LPPPquIiAjFx8erd+/e+uKLLzR//nzNnz9f0s+XD8bGxio+Pl5hYWEKCwtTfHy8vLy81LdvX0mSr6+vhg4dqnHj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BIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAATELYAAAAAwASELQAAAAAwAWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATODUYWv69Ol64IEH5OPjo4CAAD322GM6fvy4XR/DMBQXF6eQkBB5enoqMjJSR48eteuTlZWlZ555RlWrVpW3t7d69Oihc+fO/ZaHAgAAAKCcceqwtX37do0cOVJ79uzRpk2bdOPGDXXq1ElXrlyx9UlISNDMmTM1e/ZsJSUlKSgoSB07dlRmZqatT2xsrNasWaOVK1dq586dunz5sqKjo5Wbm+uIwwIAAABQDrg6uoDibNiwwW554cKFCggI0L59+/TII4/IMAzNmjVLkyZNUkxMjCRp8eLFCgwM1PLlyzV8+HClp6drwYIFWrp0qTp06CBJWrZsmWrWrKnNmzerc+fOv/lxAQAAALj7OfXI1s3S09MlSX5+fpKkU6dOKSUlRZ06dbL1sVqtatu2rXbt2iVJ2rdvn3Jycuz6hISEqHHjxrY+hcnKylJGRobdAwAAAABuV5kJW4ZhaOzYsWrTpo0aN24sSUpJSZEkBQYG2vUNDAy0PZeSkiJ3d3dVqVKlyD6FmT59unx9fW2PmjVrlubhAAAAALjLlZmwNWrUKH355Zda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",
"text/plain": "<Figure size 1000x600 with 1 Axes>"
},
"metadata": {},
"output_type": "display_data"
}
]
},
{
"metadata": {},
"id": "feb5266b",
"cell_type": "markdown",
"source": "## Version check"
},
{
"metadata": {
"trusted": false
},
"id": "cced2ac8",
"cell_type": "code",
"source": "%%aip 0\nGenerate code to report my version of torch",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": false
},
"id": "8ed42c35",
"cell_type": "code",
"source": "import torch\nprint(f\"PyTorch version: {torch.__version__}\")",
"execution_count": 18,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": "PyTorch version: 2.4.0\n"
}
]
},
{
"metadata": {
"trusted": false
},
"id": "34b45e3e",
"cell_type": "code",
"source": "print(f\"Numpy version: {np.__version__}\")",
"execution_count": 20,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": "Numpy version: 2.0.1\n"
}
]
},
{
"metadata": {
"trusted": false
},
"id": "5d26a2d8",
"cell_type": "code",
"source": "import os\ncpu_count = os.cpu_count()\ntry:\n with open(\"/proc/meminfo\",'r') as mem:\n meminfo = next(mem)\nexcept:\n meminfo ='unknown'\nprint(f\"CPU: {cpu_count} logical cores\")\nprint(meminfo)",
"execution_count": 26,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": "CPU: 16 logical cores\nMemTotal: 131177156 kB\n\n"
}
]
}
],
"metadata": {
"kernelspec": {
"name": "python3",
"display_name": "Python 3 (ipykernel)",
"language": "python"
},
"language_info": {
"name": "python",
"version": "3.12.0",
"mimetype": "text/x-python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"pygments_lexer": "ipython3",
"nbconvert_exporter": "python",
"file_extension": ".py"
},
"gist": {
"id": "",
"data": {
"description": "Shuffling in torch vs numpy-public.ipynb",
"public": true
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment