Skip to content

Instantly share code, notes, and snippets.

@emfomenk
Created March 20, 2020 04:41
Show Gist options
  • Save emfomenk/bc1a8752e31defe9999ee36c4d89150d to your computer and use it in GitHub Desktop.
Save emfomenk/bc1a8752e31defe9999ee36c4d89150d to your computer and use it in GitHub Desktop.
Play with uninitialized memory
#define _XOPEN_SOURCE 700
#include <sys/types.h>
#include <fcntl.h> /* open */
#include <stdint.h> /* uint64_t */
#include <stdio.h> /* printf */
#include <stdlib.h> /* size_t */
#include <unistd.h> /* pread, sysconf */
#include <sys/mman.h>
#include <malloc.h>
#include <iostream>
#include <chrono>
#include <cmath>
#include "dnnl.hpp"
int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr);
template<typename T>
void init_random(int size, T* ptr) {
for (int i=0; i<size; ++i)
ptr[i] = static_cast<T>(127.0f*static_cast<float>(rand()) / static_cast <float> (RAND_MAX));
}
template<typename T>
void init_zero(int size, T* ptr) {
for (int i=0; i<size; ++i)
ptr[i] = static_cast<T>(0);
}
void *my_malloc(size_t size) {
return memalign(4*1024, size);
}
int main() {
int m = 10;
int n = 3072;
int k = 768;
int iters = 1000;
char trans_a = 'N';
char trans_b = 'N';
char offsetc = 'F';
float alpha = 1.0f;
int lda = k;
uint8_t ao = 0;
int ldb = n;
int8_t bo = 0;
float beta = 0.0f;
int ldc = n;
std::array<int32_t, 1> oc = {0};
pid_t pid = getpid();
void* weights_p = my_malloc(k*n*sizeof(int8_t));
int8_t* weights = static_cast<int8_t*>(weights_p);
// mlock(weights, k*n*sizeof(int8_t));
void* input_p = my_malloc(m*k*sizeof(uint8_t));
uint8_t* input = static_cast<uint8_t*>(input_p);
init_random(m*k, input);
void* output_p = my_malloc(m*n*sizeof(int));
int* output = static_cast<int*>(output_p);
auto bench = [&](const char *str) {
float total=0.0f;
int dryrun=3;
for (int i=0; i<iters; ++i) {
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
dnnl_gemm_u8s8s32(trans_a, trans_b, offsetc,
m, n, k, alpha, const_cast<const uint8_t*>(input), lda, ao,
const_cast<const int8_t*>(weights), ldb, bo,
beta, output, ldc, oc.data());
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
if (i>=dryrun)
total += std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
}
float time = total/(iters-dryrun);
printf("%s memory: %g ms. Physical addresses: ", str, time);
for (auto *p = weights; p < weights + k * n; p += 4096 / sizeof(*weights)) {
void *phys;
virt_to_phys_user((uintptr_t *)&phys, pid, (uintptr_t)p);
printf("%p ", phys);
}
printf("\n");
};
bench("Uninitialized");
init_zero(k*n, weights);
bench("Initialized");
return 0;
}
// source: https://stackoverflow.com/a/45128487
typedef struct {
uint64_t pfn : 54;
unsigned int soft_dirty : 1;
unsigned int file_page : 1;
unsigned int swapped : 1;
unsigned int present : 1;
} PagemapEntry;
/* Parse the pagemap entry for the given virtual address.
*
* @param[out] entry the parsed entry
* @param[in] pagemap_fd file descriptor to an open /proc/pid/pagemap file
* @param[in] vaddr virtual address to get entry for
* @return 0 for success, 1 for failure
*/
int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr)
{
size_t nread;
ssize_t ret;
uint64_t data;
uintptr_t vpn;
vpn = vaddr / sysconf(_SC_PAGE_SIZE);
nread = 0;
while (nread < sizeof(data)) {
ret = pread(pagemap_fd, &data, sizeof(data) - nread,
vpn * sizeof(data) + nread);
nread += ret;
if (ret <= 0) {
return 1;
}
}
entry->pfn = data & (((uint64_t)1 << 54) - 1);
entry->soft_dirty = (data >> 54) & 1;
entry->file_page = (data >> 61) & 1;
entry->swapped = (data >> 62) & 1;
entry->present = (data >> 63) & 1;
return 0;
}
/* Convert the given virtual address to physical using /proc/PID/pagemap.
*
* @param[out] paddr physical address
* @param[in] pid process to convert for
* @param[in] vaddr virtual address to get entry for
* @return 0 for success, 1 for failure
*/
int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr)
{
char pagemap_file[BUFSIZ];
int pagemap_fd;
snprintf(pagemap_file, sizeof(pagemap_file), "/proc/%ju/pagemap", (uintmax_t)pid);
pagemap_fd = open(pagemap_file, O_RDONLY);
if (pagemap_fd < 0) {
return 1;
}
PagemapEntry entry;
if (pagemap_get_entry(&entry, pagemap_fd, vaddr)) {
return 1;
}
close(pagemap_fd);
*paddr = (entry.pfn * sysconf(_SC_PAGE_SIZE)) + (vaddr % sysconf(_SC_PAGE_SIZE));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment