An approach
- A combined list called
CountedResourceList is created in the resource list of each thread, which stores <resource-id, total occurrence count of that id> in descending order of quantity. It takes O (rt * log (rt)) time. Why? this is explained in the example run below. Also in the same iteration, we create a HashMap so that we can find in O (1) the time at which this resource identifier is indicated in the list of threads (based on the idea of โโan Inverted pointer for those that may be relevant). - Then we create a matrix -
SortedListMatrix - from t rows and r columns. In this matrix, we start by placing the resource identifiers from the CountedResourceList in this stream line, which originally contained this maximum occurring resource identifier. Thus, resource identifiers come out in the order most often found in the least encountered. - To help with the insertion of resource identifiers, we also create an
int[t] FreeColumnCount that counts the number of free columns for each stream. Since a stream with fewer free slots has less ability to move the resource identifier in case of conflict, the resource identifier will first be filled in the line with the smallest free slots for streams containing this resource identifier. - Starting from the 0th column of the first stream that contains the highest resource identifier, we select the location for the next id using the formulas
row = GetRowForResource(id) in the HashMap, and column = (column+1)%r . If the final column in the row is busy, we take the next unallocated column value by iterating the column value using the same formula without changing the row. Therefore, the columns are subject to wrapping, and the rows are determined from the HashMap, so the resource identifier is included in the correct list and in the least conflicting place . - Once this matrix is โโfull, start at row 0 and assign rows to each thread as your last least controversial list of resources.
Attn: I periodically mentioned the complexity of several steps, but will update soon with overall complexity at runtime. At the moment, I'm trying to find the right algorithm.
Run example
Initial Assumptions and Definitions:
- The number of threads = t , starting from thread 0 to t-1
- The number of resources for each thread = r
- Total resources for preparing a list of resources for flows will be > = r
We start with the case t = 4. T0 = {4, 3, 5}, T1 = {1, 2, 6}, T2 = {3, 1, 2}, T4 = {2, 7, 1}. Now I know that there are no more conflicts in this list. There should be a preprocessing step in which it turns out whether there should be some kind of permutation in the first place. For example, if the lists already have minimal conflicts, perhaps, or if there are no conflicts, the lists should be returned as they are. However, look at the pseudo-code in action.
First we read all the resources in all the lists and put them in separate buckets of resource identifiers. Using Counting Sort , this will be a linear step considering O (tr + constant) . However, since this simply gives the number of resource identifiers, we will need to use Merge Sort to sort the identifiers in descending order. This step will take O ((rt) log (rt)) . The result will be a list or identifiers sorted in descending order -
CountedResourceList = <3 times, id 1>, <3 times, id 2>, <2 times, id 3>, <1 time each identifier 4, 5, 6, 7>
During the same iteration, we also create an array of HashMap and FreeColumnCount .
Then we create a SortedListMatrix , which is populated starting from line = first stream to contain the max identifier of the resource (by calling GetRowForResource (id)) , column = 0. The matrix will be empty first and then populated as follows:
Initially: {_, _, _} {_, _, _} {_, _, _} {_, _, _} Taking 1st element '1' at (1, 0): {_, _, _} {1, _, _} {_, _, _} {_, _, _} Taking 2nd element '1' at (2, 1): {_, _, _} {1, _, _} {_, 1, _} {_, _, _} Taking 3rd element '1' at (3, 2): {_, _, _} {1, _, _} {_, 1, _} {_, _, 1} Taking 4th element '2' at (1, 1) as (1, 0) is already occupied: {_, _, _} {1, 2, _} {_, 1, _} {_, _, 1} Taking 5th element '2' at (2, 2): {_, _, _} {1, 2, _} {_, 1, 2} {_, _, 1} Taking 6th element '2' at (3, 0): {_, _, _} {1, 2, _} {_, 1, 2} {2, _, 1} Taking 7th element '3' at (0, 0) because row 2 has least free slots: {_, _, _} {1, 2, _} {3, 1, 2} {2, _, 1} Taking 8th element '3' at (0, 1): {_, 3, _} {1, 2, _} {3, 1, 2} {2, _, 1} Taking 9th element '4' at (0, 2): {_, 3, 4} {1, 2, _} {3, 1, 2} {2, _, 1} Taking 10th element '5' at (0, 0): {5, 3, 4} {1, 2, _} {3, 1, 2} {2, _, 1} Taking 11th element '6' at (1, 2): {5, 3, 4} {1, 2, 6} {3, 1, 2} {2, _, 1} Taking 12th element '7' at (3, 1): {5, 3, 4} {1, 2, 6} {3, 1, 2} {2, 7, 1}
The complexity of the above step will be O (rt) .
When the matrix is โโcompletely filled, T0 will be assigned row 0 as its list of resources, T1 as row 1 ...