Skip to content

Instantly share code, notes, and snippets.

@ajfriend
Last active December 12, 2021 23:52
Show Gist options
  • Save ajfriend/32571f0af1f3ea3133b6836fc861c730 to your computer and use it in GitHub Desktop.
Save ajfriend/32571f0af1f3ea3133b6836fc861c730 to your computer and use it in GitHub Desktop.
Timing for shift vs mask
all: thing run
thing:
gcc -Wall -Wextra -std=c99 -O3 test.c -o test
run:
./test
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "0a79e507-d15b-4c6a-9315-37e59159cb9d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('std', 0.373439),\n",
" ('shift', 0.376938),\n",
" ('mask', 0.388398),\n",
" ('std', 0.369996),\n",
" ('shift', 0.372787),\n",
" ('mask', 0.378223),\n",
" ('std', 0.364136),\n",
" ('shift', 0.369208),\n",
" ('mask', 0.384922),\n",
" ('std', 0.363623),\n",
" ('shift', 0.371109),\n",
" ('mask', 0.383131),\n",
" ('std', 0.364328),\n",
" ('shift', 0.372372),\n",
" ('mask', 0.37858),\n",
" ('std', 0.373202),\n",
" ('shift', 0.374185),\n",
" ('mask', 0.375033),\n",
" ('std', 0.361964),\n",
" ('shift', 0.376007),\n",
" ('mask', 0.377002),\n",
" ('std', 0.377874),\n",
" ('shift', 0.378057),\n",
" ('mask', 0.387126),\n",
" ('std', 0.362214),\n",
" ('shift', 0.388721),\n",
" ('mask', 0.376593),\n",
" ('std', 0.361955),\n",
" ('shift', 0.376942),\n",
" ('mask', 0.380763)]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s = \"\"\"\n",
"cmp_std: 0.373439\n",
"cmp_shift: 0.376938\n",
"cmp_mask: 0.388398\n",
"cmp_std: 0.369996\n",
"cmp_shift: 0.372787\n",
"cmp_mask: 0.378223\n",
"cmp_std: 0.364136\n",
"cmp_shift: 0.369208\n",
"cmp_mask: 0.384922\n",
"cmp_std: 0.363623\n",
"cmp_shift: 0.371109\n",
"cmp_mask: 0.383131\n",
"cmp_std: 0.364328\n",
"cmp_shift: 0.372372\n",
"cmp_mask: 0.378580\n",
"cmp_std: 0.373202\n",
"cmp_shift: 0.374185\n",
"cmp_mask: 0.375033\n",
"cmp_std: 0.361964\n",
"cmp_shift: 0.376007\n",
"cmp_mask: 0.377002\n",
"cmp_std: 0.377874\n",
"cmp_shift: 0.378057\n",
"cmp_mask: 0.387126\n",
"cmp_std: 0.362214\n",
"cmp_shift: 0.388721\n",
"cmp_mask: 0.376593\n",
"cmp_std: 0.361955\n",
"cmp_shift: 0.376942\n",
"cmp_mask: 0.380763\n",
"\"\"\"\n",
"\n",
"s = s.strip().splitlines()\n",
"s = [e.split() for e in s]\n",
"s = [(k[4:-1], float(v))for k,v in s]\n",
"s"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "220aa682-9fe7-4ce5-90bb-e462e146ae69",
"metadata": {},
"outputs": [],
"source": [
"from collections import defaultdict\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "85fc7996-f1d5-43dc-bba3-306401d157c2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'mask': [0.388398,\n",
" 0.378223,\n",
" 0.384922,\n",
" 0.383131,\n",
" 0.37858,\n",
" 0.375033,\n",
" 0.377002,\n",
" 0.387126,\n",
" 0.376593,\n",
" 0.380763],\n",
" 'shift': [0.376938,\n",
" 0.372787,\n",
" 0.369208,\n",
" 0.371109,\n",
" 0.372372,\n",
" 0.374185,\n",
" 0.376007,\n",
" 0.378057,\n",
" 0.388721,\n",
" 0.376942],\n",
" 'std': [0.373439,\n",
" 0.369996,\n",
" 0.364136,\n",
" 0.363623,\n",
" 0.364328,\n",
" 0.373202,\n",
" 0.361964,\n",
" 0.377874,\n",
" 0.362214,\n",
" 0.361955]}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = defaultdict(list)\n",
"\n",
"for k,v in s:\n",
" d[k].append(v)\n",
" \n",
"d = [(np.mean(v), k, v) for k,v in d.items()]\n",
"d = sorted(d, reverse=True)\n",
"d = {k: v for _, k, v in d}\n",
"d"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "748c3a32-7afd-43a3-9f63-713f23cc84f6",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "0739a46a-c7c3-41eb-8f5d-26399134fef7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x11bb3a580>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots()\n",
"\n",
"for k,v in d.items():\n",
" ax.plot(v, '-o',label=k)\n",
" \n",
"ax.legend()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "94c4837b-7a5d-4040-8d52-59f1541f5304",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"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.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#include <time.h>
// void qsort(void* base, size_t num, size_t size, int (*comparator)(const void*,const void*));
// printf("\nSorted:\n");
// for(int i = 0; i < N; i++){
// printf("%" PRIu64 "\n", a[i]);
// }
// printf("Unsorted:\n");
// for(int i = 0; i < N; i++){
// printf("%" PRIu64 "\n", a[i]);
// }
// printf("%" PRIu64 "\n", t >> 60);
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
_Static_assert((RAND_MAX & (RAND_MAX + 1u)) == 0, "RAND_MAX not a Mersenne number");
uint64_t rand64(void) {
uint64_t r = 0;
for (int i = 0; i < 64; i += RAND_MAX_WIDTH) {
r <<= RAND_MAX_WIDTH;
r ^= (unsigned) rand();
}
return r;
}
#define MAKE_CMP_FUNC(name, expression) \
int (name)(const void *p, const void *q){ \
uint64_t l = *(const uint64_t *)p; \
uint64_t r = *(const uint64_t *)q; \
expression \
if (l < r) return -1; \
if (l > r) return +1; \
return 0; \
} \
MAKE_CMP_FUNC(cmp_std,
)
MAKE_CMP_FUNC(cmp_shift,
l <<= 12;
r <<= 12;
)
MAKE_CMP_FUNC(cmp_mask,
uint64_t m = 0x000fffffffffffff;
l &= m;
r &= m;
)
// todo: maybe make this a function
#define DO_TIMING(cmp_func) \
copy(a, b, N); \
start_time = clock(); \
qsort((void*)b, N, sizeof(b[0]), (cmp_func)); \
end_time = clock(); \
time_elapsed = (end_time - start_time)/CLOCKS_PER_SEC; \
printf(#cmp_func ": %f\n", time_elapsed); \
void copy(uint64_t * x, uint64_t * y, uint64_t N){
for(uint64_t i = 0; i < N; i++){
y[i] = x[i];
}
}
int main() {
uint64_t N = 3000000;
uint64_t a[N];
uint64_t b[N];
double start_time, end_time, time_elapsed;
srand(3);
for(uint64_t i = 0; i < N; i++){
a[i] = rand64();
}
for(uint64_t i = 0; i < 10; i++){
DO_TIMING(cmp_std);
DO_TIMING(cmp_shift);
DO_TIMING(cmp_mask);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment