Skip to content

Instantly share code, notes, and snippets.

@thomasjpfan
Last active May 23, 2023 14:56
Show Gist options
  • Save thomasjpfan/8717892d17e9d379e979e96c0d693a97 to your computer and use it in GitHub Desktop.
Save thomasjpfan/8717892d17e9d379e979e96c0d693a97 to your computer and use it in GitHub Desktop.
Array API backend results
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
results = pd.read_csv("results_backend.csv")
sns.set_theme(context="paper", font_scale=1.4)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), constrained_layout=True, sharey=True)
sns.barplot(y="backend", x="duration", data=results[results["method"] == "fit"], ax=ax1)
ax1.set_xlabel("duration (sec)")
ax1.set_title("fit")
sns.barplot(y="backend", x="duration", data=results[results["method"] == "predict"], ax=ax2)
ax2.set_xlabel("duration (sec)")
ax2.set_title("predict")
fig.suptitle("LinearDiscriminantAnalysis")
fig.savefig("results_backend.png")
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "91d24835-d13b-4ac1-b4f2-47925ddb4a2a",
"metadata": {
"tags": []
},
"source": [
"# Array API example for LinearDiscriminantAnalysis\n",
"\n",
"### This benchmark is ran on a Nvidia GTX 3090 and a AMD 5950x."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "a849ca35-90d9-4783-810d-18250bc021ee",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.datasets import make_classification\n",
"from sklearn.discriminant_analysis import LinearDiscriminantAnalysis\n",
"import numpy as np\n",
"\n",
"X_np, y_np = make_classification(random_state=0,\n",
" n_samples=500_000, n_features=300)\n",
"X_np, y_np = X_np.astype(np.float32), y_np.astype(np.float32)\n",
"lda_np = LinearDiscriminantAnalysis()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "df3f5982-7124-4b7e-8625-9f4b3f0ccce0",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from time import perf_counter\n",
"from functools import wraps\n",
"\n",
"\n",
"def timeit(f):\n",
" @wraps(f)\n",
" def wrap(*args, **kwargs):\n",
" timing_results = []\n",
" for _ in range(10):\n",
" start = perf_counter()\n",
" obj = f(*args, **kwargs)\n",
" end = perf_counter()\n",
" timing_results.append(end - start)\n",
" return (obj, timing_results)\n",
" return wrap"
]
},
{
"cell_type": "markdown",
"id": "8eefb285-86e8-4472-ac98-bd292e7e0546",
"metadata": {},
"source": [
"## Fit runtime for NumPy array"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a1831332-4c8e-4dcf-abdc-f202e747dad1",
"metadata": {},
"outputs": [],
"source": [
"@timeit\n",
"def lda_np_fit():\n",
" return lda_np.fit(X_np, y_np)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "0ad52981-e0ca-4c98-ae72-dbd7e3e8e58b",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"lda_np_fitted, lda_np_fit_results = lda_np_fit()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "1d6122df-89b0-48c3-91a3-3a5660c13121",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[8.810645872999885,\n",
" 8.587102982000033,\n",
" 8.609924614000192,\n",
" 8.626463392000005,\n",
" 8.608467103000294,\n",
" 8.605862218999391,\n",
" 8.58534724600031,\n",
" 8.599541786999907,\n",
" 8.61696801800008,\n",
" 8.576224698999795]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lda_np_fit_results"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "9f607159-5c5d-457b-802a-63dca5de7ffc",
"metadata": {},
"outputs": [],
"source": [
"@timeit\n",
"def lda_np_predict():\n",
" return lda_np_fitted.predict(X_np)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "fbbcd4c2-0622-452c-b1e8-d6e210b70821",
"metadata": {},
"outputs": [],
"source": [
"_, lda_np_predict_results = lda_np_predict()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "6f088166-8110-418c-80af-eeb92802298f",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[0.08871091099990736,\n",
" 0.05650611500004743,\n",
" 0.055986266000218166,\n",
" 0.05600439800036838,\n",
" 0.05713565599944559,\n",
" 0.056569228000626026,\n",
" 0.057239217999267566,\n",
" 0.05904736999946181,\n",
" 0.05779621799956658,\n",
" 0.0582447159995354]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lda_np_predict_results"
]
},
{
"cell_type": "markdown",
"id": "d1049837-e4b0-4494-84f7-b5e13f08d979",
"metadata": {},
"source": [
"## Runtime for PyTorch Tensor on CPU"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "533eb684-e901-4f02-a69a-cde47f9194db",
"metadata": {},
"outputs": [],
"source": [
"import sklearn\n",
"\n",
"# Enable ArrayAPI dispatching\n",
"sklearn.set_config(array_api_dispatch=True)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4abbfdc0-1462-46a7-b010-67d3541dba14",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"\n",
"X_torch_cpu = torch.asarray(X_np)\n",
"y_torch_cpu = torch.asarray(y_np)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "e26bb8a1-1351-44c2-bb44-134b503a6bdd",
"metadata": {},
"outputs": [],
"source": [
"lda_torch_cpu = LinearDiscriminantAnalysis()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "2452d076-e6c8-4e93-95af-bdc35cc7e969",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"@timeit\n",
"def lda_torch_cpu_fit():\n",
" return lda_torch_cpu.fit(X_torch_cpu, y_torch_cpu)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "2874e1f6-b3d8-43df-87eb-c86ea00bc00f",
"metadata": {},
"outputs": [],
"source": [
"lda_torch_cpu_fitted, lda_torch_cpu_results = lda_torch_cpu_fit()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "55972e19-31d9-49a9-a768-9514fae29119",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[2.1913781430002928,\n",
" 2.1136891670003024,\n",
" 2.11096386600002,\n",
" 2.1185161840003275,\n",
" 2.1079952070003856,\n",
" 2.1046235730000262,\n",
" 2.1081806709999,\n",
" 2.1231324580003275,\n",
" 2.105008405999797,\n",
" 2.107129447999796]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lda_torch_cpu_results"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "188951d7-174e-44a2-a9e1-6e91eb8ef19b",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"@timeit\n",
"def lda_torch_cpu_predict():\n",
" return lda_torch_cpu_fitted.predict(X_torch_cpu)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "a84c01b8-31d1-41ee-a569-aafa17b978dc",
"metadata": {},
"outputs": [],
"source": [
"_, lda_torch_cpu_predict_results = lda_torch_cpu_predict()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "41aa1660-b698-4497-b0f0-548e9c052c64",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[0.04564668300008634,\n",
" 0.045281728000190924,\n",
" 0.04380844199931744,\n",
" 0.043470056000842305,\n",
" 0.04354761700051313,\n",
" 0.04359560900047654,\n",
" 0.04358013799992477,\n",
" 0.04370723000010912,\n",
" 0.04378476199963188,\n",
" 0.04336299499937013]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lda_torch_cpu_predict_results"
]
},
{
"cell_type": "markdown",
"id": "9f8e7614-3b48-4955-8c02-4883c91fd327",
"metadata": {
"tags": []
},
"source": [
"## Runtime for PyTorch Tensor on CUDA"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "56eae76f-1837-48f4-a8f7-ba29c96b7d34",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"\n",
"X_torch_cuda = torch.asarray(X_np, device=\"cuda\")\n",
"y_torch_cuda = torch.asarray(y_np, device=\"cuda\")"
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "72d982d1-e119-4732-89d0-ebb1abfeb16f",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"<_LinalgBackend.Magma: 2>"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"torch.backends.cuda.preferred_linalg_library(backend=\"cusolver\")"
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "ea84e268-4ca3-46fe-b5b8-cb5b90799bbe",
"metadata": {},
"outputs": [],
"source": [
"lda_torch_cuda = LinearDiscriminantAnalysis()"
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "f828fcfc-ffc2-4ded-960f-d8151b624def",
"metadata": {},
"outputs": [],
"source": [
"@timeit\n",
"def lda_torch_cuda_fit():\n",
" estimator = lda_torch_cuda.fit(X_torch_cuda, y_torch_cuda)\n",
" torch.cuda.synchronize(device=\"cuda\")\n",
" return estimator"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "63da0e07-b1c2-4b20-b555-e721d2fe0937",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"lda_torch_cuda_fitted, lda_torch_cuda_fit_results = lda_torch_cuda_fit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fbbe9e5e-fec6-4473-bd6a-9c1ff1b8dbd6",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1.6305857569996078,\n",
" 1.286529824000354,\n",
" 1.2996333269993556,\n",
" 1.2970852680000462,\n",
" 1.2934086249997563,\n",
" 1.296390262999921,\n",
" 1.2898022469998978,\n",
" 1.2930832319998444,\n",
" 1.2895233599992935,\n",
" 1.2903313120004896]"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lda_torch_cuda_fit_results"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "95c8e8ac-2f86-4124-9a7f-fc0e206bfd2d",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[0.25046479899992846,\n",
" 0.1450287659999958,\n",
" 0.14491702299983444,\n",
" 0.14419636799993896,\n",
" 0.1450779569995575,\n",
" 0.14480055200056086,\n",
" 0.1447656400005144,\n",
" 0.14485644300020795,\n",
" 0.14488236299985147,\n",
" 0.14417577800031722]"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lda_torch_cuda_fit_results"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "4330b786-1138-443b-90f1-ad314c568d6b",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"@timeit\n",
"def lda_torch_cuda_predict():\n",
" results = lda_torch_cuda_fitted.predict(X_torch_cuda)\n",
" torch.cuda.synchronize(device=\"cuda\")\n",
" return results"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "eba519d0-1be1-44ac-8f78-909055e78c91",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"_, lda_torch_cuda_predict_results = lda_torch_cuda_predict()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0fc04c60-59c6-44c2-8caa-77b5d0431091",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "6246f8bf-3d64-492d-9b60-94dc78b28e51",
"metadata": {},
"source": [
"## CuPy"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "27e0d677-4fca-4877-a124-50cbb18510f2",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import cupy\n",
"\n",
"X_cupy = cupy.asarray(X_np)\n",
"y_cupy = cupy.asarray(y_np)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "f1ad8a04-9eb6-4e83-90b6-c22916d65f33",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"lda_cupy = LinearDiscriminantAnalysis()"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "a1b6cbe7-d2ca-4249-a692-c8650a92ae4b",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"@timeit\n",
"def lda_cupy_fit():\n",
" output = lda_cupy.fit(X_cupy, y_cupy)\n",
" cupy.cuda.stream.get_current_stream().synchronize()\n",
" return output"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "003d02a2-fdf4-47ec-a5c5-6b06d8117777",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"lda_cupy_fitted, lda_cupy_fit_results = lda_cupy_fit()"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "a07d50e8-4180-4e62-8a95-7b15c5a18c69",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[7.996332292999796,\n",
" 1.0802618310008256,\n",
" 1.0704534280002918,\n",
" 1.0702662650001002,\n",
" 1.0701622730002782,\n",
" 1.0705247719997715,\n",
" 1.069933341000251,\n",
" 1.0698445409998385,\n",
" 1.0655767559992455,\n",
" 1.0633999070005302]"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lda_cupy_fit_results"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "858f9424-b0ad-48d9-8016-580e73280f47",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"@timeit\n",
"def lda_cupy_predict():\n",
" output = lda_cupy_fitted.predict(X_cupy) \n",
" cupy.cuda.stream.get_current_stream().synchronize()\n",
" return output"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "6ef06857-1351-4103-9a54-f7f6ec4d8762",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"_, lda_cupy_predict_results = lda_cupy_predict()"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "bf3bbee1-c6b6-42a1-b1b1-ec8842de029c",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"[0.31758884000009857,\n",
" 0.09424744399984775,\n",
" 0.09413182200023584,\n",
" 0.09410256200044387,\n",
" 0.09428052400016895,\n",
" 0.09408385200003977,\n",
" 0.09407383100005973,\n",
" 0.09409143100037909,\n",
" 0.09409573299944896,\n",
" 0.09407538499999646]"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lda_cupy_predict_results"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6d46ab12-f302-4d1d-8661-dd4a97697cc9",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 50,
"id": "09371cc1-e20e-4755-8d41-3270fb7a4aac",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import pandas as pd\n",
"import seaborn as sns"
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "c0980ae9-9c39-4c81-99eb-b7424464cc46",
"metadata": {},
"outputs": [],
"source": [
"results = pd.concat(\n",
" [\n",
" pd.DataFrame({\"duration\": lda_np_fit_results, \"backend\": \"numpy\", \"method\": \"fit\"}),\n",
" pd.DataFrame({\"duration\": lda_np_predict_results, \"backend\": \"numpy\", \"method\": \"predict\"}),\n",
" pd.DataFrame({\"duration\": lda_torch_cpu_results, \"backend\": \"torch_cpu\", \"method\": \"fit\"}),\n",
" pd.DataFrame({\"duration\": lda_torch_cpu_predict_results, \"backend\": \"torch_cpu\", \"method\": \"predict\"}),\n",
" pd.DataFrame({\"duration\": lda_torch_cuda_fit_results, \"backend\": \"torch_cuda\", \"method\": \"fit\"}),\n",
" pd.DataFrame({\"duration\": lda_torch_cuda_predict_results, \"backend\": \"torch_cuda\", \"method\": \"predict\"}),\n",
" pd.DataFrame({\"duration\": lda_cupy_fit_results, \"backend\": \"cupy\", \"method\": \"fit\"}),\n",
" pd.DataFrame({\"duration\": lda_cupy_predict_results, \"backend\": \"cupy\", \"method\": \"predict\"}),\n",
" ]\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "4b5409ce-3965-443b-8c9b-23a4a7b1dca1",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"results.to_csv(\"results_backend.csv\", index=False)"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "ba1b9b46-c558-4710-af1b-adbaf1aacba0",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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uVtvR7xV+tW+p59+Whs2bMj0X/rvNL2+M2LKqB0Mw9Ds2bPvetu9evWSJC1dutQWa0a3gN1OUFCQJPtz+m5k9LcBoGAhWQHgEm3btlVQUJBOnDih5557zjahPF1KSoq2bNmikSNH2r1osFGjRpKkjz76SOfOnbOVb9++XSNHjrR9mL0Xzp49qxkzZuiJJ57QtWvX9MADD+jNN9/M0rorVqzQ9OnTFRMTY1d+8eJFzZ8/X5JUp04dW3ndunXVoUMHJScn67nnntPOnTvt1jt16pQ++eSTHB5R3pP++1+9erXWr19vK7948aJefvll2zwiZ0p/eMTWrVsdlkVHR9sS5G7dut12O+lPtFu9enWmiU9WNWjQQB4eHtq5c6fdVYdr165pzJgxObrC1K1bNxUuXFhLly5VTEyM7r///gyvZG7evFkTJkzQ0aNH7cqvXr2qzz//XJL9OZ2Z7P5tAChYmLMCQJ9//vltv5EeMWJElp/sk1Vubm6aOnWqhg4dqm3btqlTp06qXLmyypUrp2vXrunEiRO2D3S3vpF80KBBWrVqlfbt26e2bduqevXqSkxM1IkTJ/Tggw+qW7du+vLLL3Mc37hx42zzRm7cuKHY2FidPXvWtrxjx4565513svQkMOnmvIYpU6ZoypQp8vPz03333acbN27o2LFjSk5O1n333adXXnnFbp333ntPFy5c0Pbt29W3b19VrFjR9s6N8+fPy9vbO9N3reRX/v7+6tSpkyIjIzV48GBVrlxZJUuW1JEjR2QYht5++23985//dOo+O3bsqJ9//lnvvPOOvv76a9uTwt58803bm+X9/f1Vs2bN227nkUceUalSpXTp0iWtW7fO7vHA2eXr66unn35an332mcaMGaNp06apXLlyOnbsmBITE/Xuu+/q7bffvqttly1bVo8++qjWrl0ryf6N9be6evWqvvzyS3355ZcqU6aMKlasqJSUFJ04cUKJiYkqXrx4lpL5u/nbAFBwkKwA0PXr13X9+vXbLnd2siLd/FC0YMECLV++XKtWrdKBAwd09uxZlS5dWrVr11ZwcLDat29vd7WkQoUKWrhwoT766CNt2bJF//vf/1S+fHk988wzevHFF3N0+8utDh8+LOlmUuXl5SUfHx81a9ZMDRo0UEhISLbffZJ+lWTz5s06duyYDh8+rGLFislisahNmzYaMGCA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qXfv3goJCdG4cePUunVru8vqcXFxWr16tby9vW1l06ZN0759+zRu3Dg9/vjjtvLBgwfLMAy7WI4dO6bIyEhVqFBBktSxY0e1atVKixcv1uuvv56l45GkSZMm6dSpU5o9e7aaNm1qKx86dKjDPrNi8eLFOnz4sN5991317t1bktS/f3+NGDFCBw4csKv7yCOP6LHHHrMr69u3rzp27Ki5c+fq3Xffzfb+85r4A7EyUtLsyq5fv65VqyJIVgA4lbPHRABADm8Dq169umJjY29bJzY2NltXIjLbxp49exQSEmJLVCTJx8dH/fr109mzZ7V//367dbp27WqXqEjSmjVrVKVKFYWGhjrsw83Nze7ntm3b2hIVSSpXrpyqV69u98KvO0lLS9PatWvVuHFju0Qls31mxU8//SQfHx/16NHDrvzpp592qFusWDHb/1+/fl0XL15UWlqa6tevr71792Z733mRd+1ycvOwP809PT3VuXM3F0UEIL/KrTERAAqSHF1ZGTx4sN544w317NlTDz30kMPy7du3a9WqVRo/fnxOdqOYmBhJUs2aNR2Wpd/KFBMTo/r169vKq1Sp4lD3xIkTatasWZaShIzeMFyyZEldunQpq2ErLi5O8fHxslgsWV7nTk6dOqXKlSurcOHCduUZDX5JSUmaPn26IiIidPr0abtlBeVJaz51yum+BpX0yYB/KzY2XndxMQsAsiS3xkQAKEiylawsX77coaxx48YKCwtT8+bNFRgYqLJlyyouLk47duzQxo0b1bJlSyUlJTkl2OxcifD09MzRNgoVKpTlfWUm/TavO+3zdsvTXy526zYzqp9R2XvvvadFixapf//+CgwMlI+Pj9zd3fXpp59m6woRAMCRq8dEACgIspWsjB49Wm5ubhnOtfjll1/0yy+/OJSvX79eGzZsUPfu3bO0j4w+dKdf5Th69KjDsujoaElZu1JQrVo1HTlyJNMP/M5WtmxZeXt76/Dhw7et5+PjI0m6cuWKXfmNGzd0/vx5u7LKlStr9+7dSk5Otru68r///c9hu5GRkerevbvefvttu/IpU6Zk6zgAAI5yY0wEgIIuW8lKbkwKTJ9nER8fbyvz9fWVv7+/Vq5cqRdffNH2BK2EhAR988038vPzU506de647Q4dOmjq1KkKDw9Xr1697JbdiwTG3d1d7dq1U3h4uLZs2aIm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W7bMbjvh4eFq06aNJGnatGmyWq22f+kyu4/6f//7n1555RU1adJE/v7+6tChg2bMmKGkpCS7elFRUbJarQoPD9f69esVGhqq+vXrq3nz5vrwww+VkpKShdaUUlJStGrVKjVp0kTe3t4Oy1esWKHevXsrODhYAQEBatu2rUaOHKnjx4/b1UtMTNS0adPUqVMn1atXT40bN9bLL7+sY8eOZbjf7du3a8iQIWrcuLHq1aunNm3a6M0333QYKNu1a6e0tDStXLkyS8cDwDnoa2+ir4WZeLg6AAC3l5qaqueff17bt29Xw4YN9dBDD+nEiRN67rnnFBwc7LT9jB07Vvv27dOjjz6q1q1bq0qVKpKk7777Tt9//72Cg4PVsmVLXbt2TZs2bdLo0aN1/vx5DR48WJJUu3ZthYWFad68eQoODs5ybAcPHtSAAQOUmJioxx57TBUqVNDmzZs1efJk7dixQ5999pnc3e2/V1m3bp02bNigNm3aqFGjRtq0aZM+++wzpaamatSoUXfc5/79+5WQkKAGDRo4LJs3b57ee+893X///eratauKFi2qM2fOaPPmzerYsaPuv/9+STcHz7CwMO3evdvWNrGxsVqzZo02b96sb7/9VjVr1rRtNzw8XG+99ZaKFSum9u3by9fXV3/++afWrVun1q1bq2LFira6tWrVUtGiRRUVFWVrXwD3Fn0tfS1MygBgagsXLjQsFovxj3/8w0hLS7OVL1myxLBYLIbFYjFOnjxpK58yZYpDWbpRo0YZFovFriy9fqtWrYwzZ844rPPnn38aycnJdmXJycnGM888YwQEBBhXr161lZ88edKwWCzGlClTMjyWAQMGGK1atbIr69Onj2GxWIyff/7ZVpaWlmYMGzbMsFgsxuLFi23lW7ZsMSwWi1G3bl1j586dtvLr168bjz32mBEQEGDcuHEjw33fav78+YbFYjHWrl3rsKx79+5GixYtjMTERIdjjo+Pt/08fvx4h/gMwzB+//13o06dOsYzzzxjKzt9+rTh7+9vNGvWzDh16pRd/evXrxsXL150iKNnz55GUFDQHY8FgHPQ19LXwpy4DQwwue+++07u7u4aPny43NzcbOU9e/ZU9erVnbafZ599Vn5+fg7lFSpUkIeH/UVYDw8P9enTR9euXdOePXvuep8xMTHauXOngoOD9cgjj9jK3dzcNHLk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",
"text/plain": [
"<Figure size 800x400 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"import pandas as pd\n",
"import seaborn as sns\n",
"\n",
"results = pd.read_csv(\"results_backend.csv\")\n",
"\n",
"sns.set_theme(context=\"paper\", font_scale=1.4)\n",
"fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), constrained_layout=True, sharey=True)\n",
"sns.barplot(y=\"backend\", x=\"duration\", data=results[results[\"method\"] == \"fit\"], ax=ax1)\n",
"ax1.set_xlabel(\"duration (sec)\")\n",
"ax1.set_title(\"fit\")\n",
"\n",
"sns.barplot(y=\"backend\", x=\"duration\", data=results[results[\"method\"] == \"predict\"], ax=ax2)\n",
"ax2.set_xlabel(\"duration (sec)\")\n",
"ax2.set_title(\"predict\")\n",
"\n",
"fig.suptitle(\"LinearDiscriminantAnalysis\")\n",
"fig.savefig(\"results_backend.png\")"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "c05bfa2d-3a2f-4ded-abaa-62e9964e9100",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"fig.savefig(\"results_backend.png\")"
]
},
{
"cell_type": "markdown",
"id": "24b73a36-a142-48c0-967c-f2e40f14df83",
"metadata": {},
"source": [
"## Check coefs are the same"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "92674019-00ae-4cd7-96ab-1ada7f8dd0c0",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"np_coef_ = np.asarray(lda_np.coef_)\n",
"\n",
"# Is there a bettery way to convert cupy.array_api to a np.ndarray?\n",
"cu_coef_ = lda_torch_cuda.coef_.cpu().numpy()\n",
"\n",
"np.testing.assert_allclose(np_coef_, cu_coef_, atol=1e-3)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "sk1-pytorch (python3)",
"language": "python",
"name": "conda-env-sk1-pytorch-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
duration backend method
8.810645872999885 numpy fit
8.587102982000033 numpy fit
8.609924614000192 numpy fit
8.626463392000005 numpy fit
8.608467103000294 numpy fit
8.605862218999391 numpy fit
8.58534724600031 numpy fit
8.599541786999907 numpy fit
8.61696801800008 numpy fit
8.576224698999795 numpy fit
0.08871091099990736 numpy predict
0.05650611500004743 numpy predict
0.055986266000218166 numpy predict
0.05600439800036838 numpy predict
0.05713565599944559 numpy predict
0.056569228000626026 numpy predict
0.057239217999267566 numpy predict
0.05904736999946181 numpy predict
0.05779621799956658 numpy predict
0.0582447159995354 numpy predict
2.1913781430002928 torch_cpu fit
2.1136891670003024 torch_cpu fit
2.11096386600002 torch_cpu fit
2.1185161840003275 torch_cpu fit
2.1079952070003856 torch_cpu fit
2.1046235730000262 torch_cpu fit
2.1081806709999 torch_cpu fit
2.1231324580003275 torch_cpu fit
2.105008405999797 torch_cpu fit
2.107129447999796 torch_cpu fit
0.04564668300008634 torch_cpu predict
0.045281728000190924 torch_cpu predict
0.04380844199931744 torch_cpu predict
0.043470056000842305 torch_cpu predict
0.04354761700051313 torch_cpu predict
0.04359560900047654 torch_cpu predict
0.04358013799992477 torch_cpu predict
0.04370723000010912 torch_cpu predict
0.04378476199963188 torch_cpu predict
0.04336299499937013 torch_cpu predict
1.6305857569996078 torch_cuda fit
1.286529824000354 torch_cuda fit
1.2996333269993556 torch_cuda fit
1.2970852680000462 torch_cuda fit
1.2934086249997563 torch_cuda fit
1.296390262999921 torch_cuda fit
1.2898022469998978 torch_cuda fit
1.2930832319998444 torch_cuda fit
1.2895233599992935 torch_cuda fit
1.2903313120004896 torch_cuda fit
0.0020639669992306153 torch_cuda predict
0.001711779999823193 torch_cuda predict
0.0017488110006524948 torch_cuda predict
0.0017270009993808344 torch_cuda predict
0.001721020999866596 torch_cuda predict
0.001703330000054848 torch_cuda predict
0.0017148200004157843 torch_cuda predict
0.001706540999293793 torch_cuda predict
0.0017124300002251402 torch_cuda predict
0.0017068600000129663 torch_cuda predict
7.996332292999796 cupy fit
1.0802618310008256 cupy fit
1.0704534280002918 cupy fit
1.0702662650001002 cupy fit
1.0701622730002782 cupy fit
1.0705247719997715 cupy fit
1.069933341000251 cupy fit
1.0698445409998385 cupy fit
1.0655767559992455 cupy fit
1.0633999070005302 cupy fit
0.31758884000009857 cupy predict
0.09424744399984775 cupy predict
0.09413182200023584 cupy predict
0.09410256200044387 cupy predict
0.09428052400016895 cupy predict
0.09408385200003977 cupy predict
0.09407383100005973 cupy predict
0.09409143100037909 cupy predict
0.09409573299944896 cupy predict
0.09407538499999646 cupy predict
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment