thesis version
This commit is contained in:
		
							
								
								
									
										12
									
								
								plot/common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								plot/common.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
#ifndef ALSK_PLOT_COMMON_H
 | 
			
		||||
#define ALSK_PLOT_COMMON_H
 | 
			
		||||
 | 
			
		||||
#include <set>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
using CoresList = std::vector<std::size_t>;
 | 
			
		||||
using Split = std::set<std::size_t>;
 | 
			
		||||
 | 
			
		||||
using SplitFn = Split(&)(std::size_t, CoresList const&);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										23
									
								
								plot/executor/firstlevelequi.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								plot/executor/firstlevelequi.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
#include "firstlevelequi.h"
 | 
			
		||||
 | 
			
		||||
Split firstLevelEqui(std::size_t n, CoresList const& coresList) {
 | 
			
		||||
	Split split;
 | 
			
		||||
 | 
			
		||||
	auto firstLevelPar = n;
 | 
			
		||||
 | 
			
		||||
	split.insert(0);
 | 
			
		||||
	for(auto const& k: coresList) {
 | 
			
		||||
		std::size_t start{};
 | 
			
		||||
		std::size_t const step = firstLevelPar/k;
 | 
			
		||||
		std::size_t remain = firstLevelPar - step*k;
 | 
			
		||||
 | 
			
		||||
		for(unsigned int i = 0; i < k-1; ++i) {
 | 
			
		||||
			std::size_t offset = !!remain;
 | 
			
		||||
			remain -= offset;
 | 
			
		||||
			start += step+offset;
 | 
			
		||||
			split.insert(start * (n/firstLevelPar));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return split;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								plot/executor/firstlevelequi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								plot/executor/firstlevelequi.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef ALSK_PLOT_EXECUTOR_FIRSTLEVELEQUI_H
 | 
			
		||||
#define ALSK_PLOT_EXECUTOR_FIRSTLEVELEQUI_H
 | 
			
		||||
 | 
			
		||||
#include "../common.h"
 | 
			
		||||
 | 
			
		||||
Split firstLevelEqui(std::size_t n, CoresList const& coresList);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										19
									
								
								plot/executor/firstlevelgreedy.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								plot/executor/firstlevelgreedy.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
#include "firstlevelgreedy.h"
 | 
			
		||||
 | 
			
		||||
Split firstLevelGreedy(std::size_t n, CoresList const& coresList) {
 | 
			
		||||
	Split split;
 | 
			
		||||
 | 
			
		||||
	auto firstLevelPar = n;
 | 
			
		||||
 | 
			
		||||
	split.insert(0);
 | 
			
		||||
	for(auto const& k: coresList) {
 | 
			
		||||
		std::size_t start{};
 | 
			
		||||
		std::size_t const step = (firstLevelPar + k-1)/k;
 | 
			
		||||
		std::size_t const rk = (firstLevelPar + step-1)/step;
 | 
			
		||||
 | 
			
		||||
		for(unsigned int i = 0; i < rk; ++i, start += step)
 | 
			
		||||
			split.insert(start * (n/firstLevelPar));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return split;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								plot/executor/firstlevelgreedy.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								plot/executor/firstlevelgreedy.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef ALSK_PLOT_EXECUTOR_FIRSTLEVELGREEDY_H
 | 
			
		||||
#define ALSK_PLOT_EXECUTOR_FIRSTLEVELGREEDY_H
 | 
			
		||||
 | 
			
		||||
#include "../common.h"
 | 
			
		||||
 | 
			
		||||
Split firstLevelGreedy(std::size_t n, CoresList const& coresList);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										67
									
								
								plot/executor/opti.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								plot/executor/opti.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
#include "opti.h"
 | 
			
		||||
 | 
			
		||||
Split fictiveOpti(std::size_t tasks, CoresList const& coresList) {
 | 
			
		||||
	Split split;
 | 
			
		||||
 | 
			
		||||
	auto equi = [&](unsigned k) {
 | 
			
		||||
		std::vector<unsigned> ntasks;
 | 
			
		||||
		unsigned const step = tasks/k;
 | 
			
		||||
		unsigned remain = tasks - k*step;
 | 
			
		||||
 | 
			
		||||
		for(unsigned int i = 0; i < k; ++i) {
 | 
			
		||||
			unsigned q = step;
 | 
			
		||||
			if(remain) {
 | 
			
		||||
				++q;
 | 
			
		||||
				--remain;
 | 
			
		||||
			}
 | 
			
		||||
			ntasks.push_back(q);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return ntasks;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	auto greedy = [&](unsigned k) {
 | 
			
		||||
		std::vector<unsigned> ntasks;
 | 
			
		||||
		unsigned step = (tasks+k-1)/k;
 | 
			
		||||
		unsigned n = tasks;
 | 
			
		||||
 | 
			
		||||
		while(n) {
 | 
			
		||||
			if(n < step) step = n;
 | 
			
		||||
			n -= step;
 | 
			
		||||
			ntasks.push_back(step);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return ntasks;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static_cast<void>(equi);
 | 
			
		||||
	static_cast<void>(greedy);
 | 
			
		||||
 | 
			
		||||
	for(auto k: coresList) {
 | 
			
		||||
	// for(unsigned int k = cores; k > 1; --k) {
 | 
			
		||||
	// for(unsigned int k = 2; k <= cores; ++k) {
 | 
			
		||||
		auto ntasks = equi(k);
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			unsigned start{};
 | 
			
		||||
			while(ntasks.size() > 1) {
 | 
			
		||||
				auto v = std::end(ntasks);
 | 
			
		||||
				for(auto it = std::begin(ntasks);
 | 
			
		||||
						v == std::end(ntasks) && it != std::end(ntasks);
 | 
			
		||||
						++it)
 | 
			
		||||
				{
 | 
			
		||||
					if(split.count(start+*it))
 | 
			
		||||
						v = it;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if(v == std::end(ntasks)) v = std::begin(ntasks);
 | 
			
		||||
 | 
			
		||||
				start += *v;
 | 
			
		||||
				split.insert(start);
 | 
			
		||||
				ntasks.erase(v);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return split;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								plot/executor/opti.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								plot/executor/opti.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef ALSK_PLOT_EXECUTOR_OPTI_H
 | 
			
		||||
#define ALSK_PLOT_EXECUTOR_OPTI_H
 | 
			
		||||
 | 
			
		||||
#include "../common.h"
 | 
			
		||||
 | 
			
		||||
Split fictiveOpti(std::size_t n, CoresList const& coresList);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										0
									
								
								plot/executor/staticpool.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								plot/executor/staticpool.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										8
									
								
								plot/executor/staticpool.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								plot/executor/staticpool.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef ALSK_PLOT_EXECUTOR_STATICPOOL_H
 | 
			
		||||
#define ALSK_PLOT_EXECUTOR_STATICPOOL_H
 | 
			
		||||
 | 
			
		||||
#include "../common.h"
 | 
			
		||||
 | 
			
		||||
Split staticPool(std::size_t n, CoresList const& coresList);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										113
									
								
								plot/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								plot/main.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "executor/firstlevelequi.h"
 | 
			
		||||
#include "executor/firstlevelgreedy.h"
 | 
			
		||||
#include "executor/opti.h"
 | 
			
		||||
 | 
			
		||||
void displaySplit(Split const& split) {
 | 
			
		||||
	for(auto const& e: split)
 | 
			
		||||
		std::printf("%zu, ", e);
 | 
			
		||||
	std::puts("");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::ostream& operator<<(std::ostream& os, CoresList const& cl) {
 | 
			
		||||
	os << '{';
 | 
			
		||||
	for(auto k: cl) os << k << ',';
 | 
			
		||||
	return os << '}';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CoresList coresLinUpTo(std::size_t n) {
 | 
			
		||||
	CoresList cl(n);
 | 
			
		||||
	std::generate_n(std::begin(cl), n, [i=0]() mutable { return ++i; });
 | 
			
		||||
	return cl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CoresList coresExpUpTo(std::size_t n) {
 | 
			
		||||
	CoresList cl;
 | 
			
		||||
	std::size_t min = 1;
 | 
			
		||||
	while(min <= n) {
 | 
			
		||||
		cl.push_back(min);
 | 
			
		||||
		min *= 2;
 | 
			
		||||
	}
 | 
			
		||||
	return cl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* *** */
 | 
			
		||||
 | 
			
		||||
void genFixedCores(std::string const& o, CoresList const& coresList, std::size_t first, std::size_t last, SplitFn split) {
 | 
			
		||||
	std::ofstream f{o};
 | 
			
		||||
	if(!f) return;
 | 
			
		||||
 | 
			
		||||
	f << *coresList.rbegin() << ',' << first << ',' << last << '\n';
 | 
			
		||||
	for(std::size_t n = first; n <= last; ++n)
 | 
			
		||||
		f << n << ',' << split(n, coresList).size() << '\n';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void genFixedTasksLin(std::string const& o, std::size_t tasks, std::size_t last, SplitFn split) {
 | 
			
		||||
	std::ofstream f{o};
 | 
			
		||||
	if(!f) return;
 | 
			
		||||
 | 
			
		||||
	f << tasks << ',' << 1 << ',' << last << '\n';
 | 
			
		||||
	for(std::size_t i = 1; i <= last; ++i)
 | 
			
		||||
		f << i << ',' << split(i, coresLinUpTo(i)).size() << '\n';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void genFixedTasksExp(std::string const& o, std::size_t tasks, std::size_t last, SplitFn split) {
 | 
			
		||||
	std::ofstream f{o};
 | 
			
		||||
	if(!f) return;
 | 
			
		||||
 | 
			
		||||
	f << tasks << ',' << 1 << ',' << last << '\n';
 | 
			
		||||
	for(std::size_t i = 1; i <= last; i *= 2)
 | 
			
		||||
		f << i << ',' << split(i, coresExpUpTo(i)).size() << '\n';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void genAll() {
 | 
			
		||||
#define OUTPREFIX "plot_data/fig"
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		auto cores                = coresLinUpTo(64);
 | 
			
		||||
		constexpr unsigned start  = 50;
 | 
			
		||||
		constexpr unsigned num    = 1000;
 | 
			
		||||
		genFixedCores(OUTPREFIX "1a", cores, start, start+num, firstLevelEqui);
 | 
			
		||||
		genFixedCores(OUTPREFIX "1b", cores, start, start+num, firstLevelGreedy);
 | 
			
		||||
		genFixedCores(OUTPREFIX "1c", cores, start, start+num, fictiveOpti);
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		auto cores                = coresLinUpTo(64);
 | 
			
		||||
		constexpr unsigned start  = 50;
 | 
			
		||||
		constexpr unsigned num    = 1000;
 | 
			
		||||
		genFixedCores(OUTPREFIX "2a", cores, start, start+num, firstLevelEqui);
 | 
			
		||||
		genFixedCores(OUTPREFIX "2b", cores, start, start+num, firstLevelGreedy);
 | 
			
		||||
		genFixedCores(OUTPREFIX "2c", cores, start, start+num, fictiveOpti);
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		auto cores                = coresLinUpTo(64);
 | 
			
		||||
		constexpr unsigned start  = 50;
 | 
			
		||||
		constexpr unsigned num    = 1000;
 | 
			
		||||
		genFixedCores(OUTPREFIX "3a", cores, start, start+num, firstLevelEqui);
 | 
			
		||||
		genFixedCores(OUTPREFIX "3b", coresExpUpTo(64), start, start+num, firstLevelEqui);
 | 
			
		||||
		genFixedCores(OUTPREFIX "3c", cores, start, start+num, fictiveOpti);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		constexpr unsigned tasks  = 1000;
 | 
			
		||||
		genFixedTasksLin(OUTPREFIX "4a", tasks, 256, firstLevelEqui);
 | 
			
		||||
		genFixedTasksLin(OUTPREFIX "4b", tasks, 256, firstLevelGreedy);
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		constexpr unsigned tasks  = 10'000;
 | 
			
		||||
		genFixedTasksLin(OUTPREFIX "5a", tasks, 256, firstLevelEqui);
 | 
			
		||||
		genFixedTasksLin(OUTPREFIX "5b", tasks, 256, firstLevelGreedy);
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		constexpr unsigned tasks  = 1'000'000;
 | 
			
		||||
		genFixedTasksLin(OUTPREFIX "6a", tasks, 256, firstLevelEqui);
 | 
			
		||||
		genFixedTasksLin(OUTPREFIX "6b", tasks, 256, firstLevelGreedy);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
	genAll();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										141
									
								
								plot/mkplot
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										141
									
								
								plot/mkplot
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
import os, sys
 | 
			
		||||
sys.path.append(os.path.abspath(os.path.dirname(os.path.abspath(__file__))+"/../scripts"))
 | 
			
		||||
 | 
			
		||||
import fileinput
 | 
			
		||||
import numpy as np
 | 
			
		||||
import matplotlib as mpl
 | 
			
		||||
 | 
			
		||||
show = len(sys.argv) > 1 and sys.argv[1] == 'show'
 | 
			
		||||
if not show:
 | 
			
		||||
	mpl.use('pgf')
 | 
			
		||||
 | 
			
		||||
import matplotlib.pyplot as plt
 | 
			
		||||
import matplotlib.lines as lines
 | 
			
		||||
from common import set_size, config_plt
 | 
			
		||||
 | 
			
		||||
config_plt()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def loadData(fn):
 | 
			
		||||
	xs = []
 | 
			
		||||
	ys = []
 | 
			
		||||
	content = []
 | 
			
		||||
 | 
			
		||||
	cst = 0
 | 
			
		||||
	inf = 0
 | 
			
		||||
	sup = 0
 | 
			
		||||
 | 
			
		||||
	with open(fn) as f:
 | 
			
		||||
		cst, inf, sup = [float(x) for x in f.readline().split(',')]
 | 
			
		||||
		content = f.readlines()
 | 
			
		||||
 | 
			
		||||
	for line in content:
 | 
			
		||||
		tok = line.split(',')
 | 
			
		||||
		xs.append(float(tok[0]))
 | 
			
		||||
		ys.append(float(tok[1]))
 | 
			
		||||
 | 
			
		||||
	return [[cst, inf, sup], xs, ys]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def drawLine(plt, b, e, label, color):
 | 
			
		||||
	x = np.arange(b, e, 1)
 | 
			
		||||
	plt.plot(x, x, label=label, color=color);
 | 
			
		||||
 | 
			
		||||
def drawHLine(plt, b, e, v, color):
 | 
			
		||||
	x = np.arange(b, e, 1)
 | 
			
		||||
	plt.plot(x, [v]*(e-b), color=color);
 | 
			
		||||
 | 
			
		||||
def drawCloud(plt, data, label, color):
 | 
			
		||||
	x, y = data
 | 
			
		||||
	plt.scatter(x, y, label=label, s=3, linewidth=0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def figCores(n, lblA, lblB):
 | 
			
		||||
	name = 'fig'+str(n)
 | 
			
		||||
 | 
			
		||||
	fig = plt.figure()
 | 
			
		||||
 | 
			
		||||
	data = loadData('plot_data/'+name+'a')
 | 
			
		||||
	cst, inf, sup = data[0]
 | 
			
		||||
 | 
			
		||||
	#  plt.title(u"nombre de cœurs fixe = " + str(int(cst)))
 | 
			
		||||
	plt.xlabel(u'tâches')
 | 
			
		||||
	plt.ylabel(u'PRNG')
 | 
			
		||||
 | 
			
		||||
	drawLine(plt, inf, sup, u"sans optimisation", 'red')
 | 
			
		||||
	drawCloud(plt, data[1:], lblA, 'blue')
 | 
			
		||||
 | 
			
		||||
	data = loadData('plot_data/'+name+'b')
 | 
			
		||||
	drawCloud(plt, data[1:], lblB, 'green')
 | 
			
		||||
 | 
			
		||||
	fig.set_size_inches(set_size(455.24408, .8))
 | 
			
		||||
 | 
			
		||||
	fig.legend()
 | 
			
		||||
 | 
			
		||||
	if not show:
 | 
			
		||||
		fig.savefig('plots/'+name+'.pdf', format='pdf', bbox_inches='tight')
 | 
			
		||||
	return plt
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def figTasks(n):
 | 
			
		||||
	name = 'fig'+str(n)
 | 
			
		||||
 | 
			
		||||
	fig = plt.figure()
 | 
			
		||||
	width = 3.487
 | 
			
		||||
	height = width/1.618
 | 
			
		||||
 | 
			
		||||
	data = loadData('plot_data/'+name+'a')
 | 
			
		||||
	cst, inf, sup = data[0]
 | 
			
		||||
 | 
			
		||||
	plt.title(u"nombre de tâches fixe = " + str(int(cst)))
 | 
			
		||||
	plt.xlabel(u'cœurs')
 | 
			
		||||
	plt.ylabel(u'PRNG')
 | 
			
		||||
 | 
			
		||||
	drawCloud(plt, data[1:], 'equilibrated distribution', 'blue')
 | 
			
		||||
 | 
			
		||||
	data = loadData('plot_data/'+name+'b')
 | 
			
		||||
	drawCloud(plt, data[1:], 'greedy distribution', 'green')
 | 
			
		||||
 | 
			
		||||
	fig.set_size_inches(set_size(455.24408, .8))
 | 
			
		||||
 | 
			
		||||
	fig.legend()
 | 
			
		||||
 | 
			
		||||
	if not show:
 | 
			
		||||
		fig.savefig('plots/'+name+'.pdf', format='pdf', bbox_inches='tight')
 | 
			
		||||
	return plt
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fig1():
 | 
			
		||||
	return figCores(1, u"politique d'exécution 1", u"politique d'exécution 2")
 | 
			
		||||
 | 
			
		||||
def fig2():
 | 
			
		||||
	return figCores(2, u"politique d'exécution 1", u"politique d'exécution 2")
 | 
			
		||||
 | 
			
		||||
def fig3():
 | 
			
		||||
	return figCores(3, u"$\mathbf{T} = \{1, 2, 3, 4, 5, 6, ..., 64\}$", u"$\mathbf{T} = \{1, 2, 4, 8, 16, 32, 64\}$")
 | 
			
		||||
 | 
			
		||||
def fig4():
 | 
			
		||||
	return figTasks(4)
 | 
			
		||||
 | 
			
		||||
def fig5():
 | 
			
		||||
	return figTasks(5)
 | 
			
		||||
 | 
			
		||||
def fig6():
 | 
			
		||||
	return figTasks(6)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
plts = []
 | 
			
		||||
 | 
			
		||||
plts.append(fig1())
 | 
			
		||||
plts.append(fig2())
 | 
			
		||||
plts.append(fig3())
 | 
			
		||||
plts.append(fig4())
 | 
			
		||||
plts.append(fig5())
 | 
			
		||||
plts.append(fig6())
 | 
			
		||||
 | 
			
		||||
if show:
 | 
			
		||||
	for plt in plts:
 | 
			
		||||
		plt.show()
 | 
			
		||||
		Reference in New Issue
	
	Block a user