未验证 提交 5643d156 编写于 作者: S shuai.xus 提交者: Till Rohrmann

[FLINK-7928] [runtime] extend the resources in ResourceProfile for precisely...

[FLINK-7928] [runtime] extend the resources in ResourceProfile for precisely calculating the resource of task manager

Summary:
ResourceProfile denotes the resource requirements of a task. It should contains:
1. The resource for the operators: the resources in ResourceSpec (please refer to jira-7878)
2. The resource for the task to communicate with its upstreams.
3. The resource for the task to communicate with its downstreams.
Now the ResourceProfile only contains the first part. Adding the last two parts.

Test Plan: UnitTests

Reviewers: haitao.w

Differential Revision: https://aone.alibaba-inc.com/code/D330364

This closes #4991.
上级 fba72d07
...@@ -54,7 +54,7 @@ public class ResourceSpec implements Serializable { ...@@ -54,7 +54,7 @@ public class ResourceSpec implements Serializable {
public static final ResourceSpec DEFAULT = new ResourceSpec(0, 0, 0, 0, 0); public static final ResourceSpec DEFAULT = new ResourceSpec(0, 0, 0, 0, 0);
private static final String GPU_NAME = "GPU"; public static final String GPU_NAME = "GPU";
/** How many cpu cores are needed, use double so we can specify cpu like 0.1. */ /** How many cpu cores are needed, use double so we can specify cpu like 0.1. */
private final double cpuCores; private final double cpuCores;
...@@ -146,7 +146,7 @@ public class ResourceSpec implements Serializable { ...@@ -146,7 +146,7 @@ public class ResourceSpec implements Serializable {
public double getGPUResource() { public double getGPUResource() {
Resource gpuResource = extendedResources.get(GPU_NAME); Resource gpuResource = extendedResources.get(GPU_NAME);
if (gpuResource != null) { if (gpuResource != null) {
return gpuResource.value; return gpuResource.getValue();
} }
return 0.0; return 0.0;
} }
...@@ -249,8 +249,8 @@ public class ResourceSpec implements Serializable { ...@@ -249,8 +249,8 @@ public class ResourceSpec implements Serializable {
*/ */
public static class Builder { public static class Builder {
public double cpuCores; private double cpuCores;
public int heapMemoryInMB; private int heapMemoryInMB;
private int directMemoryInMB; private int directMemoryInMB;
private int nativeMemoryInMB; private int nativeMemoryInMB;
private int stateSizeInMB; private int stateSizeInMB;
...@@ -300,7 +300,7 @@ public class ResourceSpec implements Serializable { ...@@ -300,7 +300,7 @@ public class ResourceSpec implements Serializable {
/** /**
* Base class for additional resources one can specify. * Base class for additional resources one can specify.
*/ */
protected abstract static class Resource implements Serializable { public abstract static class Resource implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
...@@ -372,6 +372,18 @@ public class ResourceSpec implements Serializable { ...@@ -372,6 +372,18 @@ public class ResourceSpec implements Serializable {
return result; return result;
} }
public String getName() {
return this.name;
}
public ResourceAggregateType getAggregateType() {
return this.type;
}
public double getValue() {
return this.value;
}
/** /**
* Create a resource of the same resource type. * Create a resource of the same resource type.
* *
......
...@@ -18,19 +18,30 @@ ...@@ -18,19 +18,30 @@
package org.apache.flink.runtime.clusterframework.types; package org.apache.flink.runtime.clusterframework.types;
import org.apache.flink.api.common.operators.ResourceSpec;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
/** /**
* Describe the resource profile of the slot, either when requiring or offering it. The profile can be * Describe the immutable resource profile of the slot, either when requiring or offering it. The profile can be
* checked whether it can match another profile's requirement, and furthermore we may calculate a matching * checked whether it can match another profile's requirement, and furthermore we may calculate a matching
* score to decide which profile we should choose when we have lots of candidate slots. * score to decide which profile we should choose when we have lots of candidate slots.
* It should be generated from {@link ResourceSpec} with the input and output memory calculated in JobMaster.
* *
* <p>Resource Profiles have a total ordering, defined by comparing these fields in sequence: * <p>Resource Profiles have a total ordering, defined by comparing these fields in sequence:
* <ol> * <ol>
* <li>Memory Size</li> * <li>Memory Size</li>
* <li>CPU cores</li> * <li>CPU cores</li>
* <li>Extended resources</li>
* </ol> * </ol>
* The extended resources are compared ordered by the resource names.
*/ */
public class ResourceProfile implements Serializable, Comparable<ResourceProfile> { public class ResourceProfile implements Serializable, Comparable<ResourceProfile> {
...@@ -52,6 +63,9 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -52,6 +63,9 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
/** How many native memory in mb are needed */ /** How many native memory in mb are needed */
private final int nativeMemoryInMB; private final int nativeMemoryInMB;
/** A extensible field for user specified resources from {@link ResourceSpec}. */
private final Map<String, ResourceSpec.Resource> extendedResources = new HashMap<>(1);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** /**
...@@ -61,16 +75,21 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -61,16 +75,21 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
* @param heapMemoryInMB The size of the heap memory, in megabytes. * @param heapMemoryInMB The size of the heap memory, in megabytes.
* @param directMemoryInMB The size of the direct memory, in megabytes. * @param directMemoryInMB The size of the direct memory, in megabytes.
* @param nativeMemoryInMB The size of the native memory, in megabytes. * @param nativeMemoryInMB The size of the native memory, in megabytes.
* @param extendedResources The extendiable resources such as GPU and FPGA
*/ */
public ResourceProfile( public ResourceProfile(
double cpuCores, double cpuCores,
int heapMemoryInMB, int heapMemoryInMB,
int directMemoryInMB, int directMemoryInMB,
int nativeMemoryInMB) { int nativeMemoryInMB,
Map<String, ResourceSpec.Resource> extendedResources) {
this.cpuCores = cpuCores; this.cpuCores = cpuCores;
this.heapMemoryInMB = heapMemoryInMB; this.heapMemoryInMB = heapMemoryInMB;
this.directMemoryInMB = directMemoryInMB; this.directMemoryInMB = directMemoryInMB;
this.nativeMemoryInMB = nativeMemoryInMB; this.nativeMemoryInMB = nativeMemoryInMB;
if (extendedResources != null) {
this.extendedResources.putAll(extendedResources);
}
} }
/** /**
...@@ -80,10 +99,7 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -80,10 +99,7 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
* @param heapMemoryInMB The size of the heap memory, in megabytes. * @param heapMemoryInMB The size of the heap memory, in megabytes.
*/ */
public ResourceProfile(double cpuCores, int heapMemoryInMB) { public ResourceProfile(double cpuCores, int heapMemoryInMB) {
this.cpuCores = cpuCores; this(cpuCores, heapMemoryInMB, 0, 0, Collections.EMPTY_MAP);
this.heapMemoryInMB = heapMemoryInMB;
this.directMemoryInMB = 0;
this.nativeMemoryInMB = 0;
} }
/** /**
...@@ -92,16 +108,14 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -92,16 +108,14 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
* @param other The ResourceProfile to copy. * @param other The ResourceProfile to copy.
*/ */
public ResourceProfile(ResourceProfile other) { public ResourceProfile(ResourceProfile other) {
this.cpuCores = other.cpuCores; this(other.cpuCores, other.heapMemoryInMB, other.directMemoryInMB, other.nativeMemoryInMB, other.extendedResources);
this.heapMemoryInMB = other.heapMemoryInMB;
this.directMemoryInMB = other.directMemoryInMB;
this.nativeMemoryInMB = other.nativeMemoryInMB;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** /**
* Get the cpu cores needed * Get the cpu cores needed.
*
* @return The cpu cores, 1.0 means a full cpu thread * @return The cpu cores, 1.0 means a full cpu thread
*/ */
public double getCpuCores() { public double getCpuCores() {
...@@ -109,15 +123,17 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -109,15 +123,17 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
} }
/** /**
* Get the heap memory needed in MB * Get the heap memory needed in MB.
*
* @return The heap memory in MB * @return The heap memory in MB
*/ */
public long getHeapMemoryInMB() { public int getHeapMemoryInMB() {
return heapMemoryInMB; return heapMemoryInMB;
} }
/** /**
* Get the direct memory needed in MB * Get the direct memory needed in MB.
*
* @return The direct memory in MB * @return The direct memory in MB
*/ */
public int getDirectMemoryInMB() { public int getDirectMemoryInMB() {
...@@ -125,7 +141,8 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -125,7 +141,8 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
} }
/** /**
* Get the native memory needed in MB * Get the native memory needed in MB.
*
* @return The native memory in MB * @return The native memory in MB
*/ */
public int getNativeMemoryInMB() { public int getNativeMemoryInMB() {
...@@ -133,7 +150,8 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -133,7 +150,8 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
} }
/** /**
* Get the total memory needed in MB * Get the total memory needed in MB.
*
* @return The total memory in MB * @return The total memory in MB
*/ */
public int getMemoryInMB() { public int getMemoryInMB() {
...@@ -141,23 +159,76 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -141,23 +159,76 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
} }
/** /**
* Check whether required resource profile can be matched * Get the memory the operators needed in MB.
*
* @return The operator memory in MB
*/
public int getOperatorsMemoryInMB() {
return heapMemoryInMB + directMemoryInMB + nativeMemoryInMB;
}
/**
* Get the extended resources.
*
* @return The extended resources
*/
public Map<String, ResourceSpec.Resource> getExtendedResources() {
return Collections.unmodifiableMap(extendedResources);
}
/**
* Check whether required resource profile can be matched.
* *
* @param required the required resource profile * @param required the required resource profile
* @return true if the requirement is matched, otherwise false * @return true if the requirement is matched, otherwise false
*/ */
public boolean isMatching(ResourceProfile required) { public boolean isMatching(ResourceProfile required) {
return cpuCores >= required.getCpuCores() && if (cpuCores >= required.getCpuCores() &&
heapMemoryInMB >= required.getHeapMemoryInMB() && heapMemoryInMB >= required.getHeapMemoryInMB() &&
directMemoryInMB >= required.getDirectMemoryInMB() && directMemoryInMB >= required.getDirectMemoryInMB() &&
nativeMemoryInMB >= required.getNativeMemoryInMB(); nativeMemoryInMB >= required.getNativeMemoryInMB()) {
for (Map.Entry<String, ResourceSpec.Resource> resource : required.extendedResources.entrySet()) {
if (!extendedResources.containsKey(resource.getKey()) ||
!extendedResources.get(resource.getKey()).getAggregateType().equals(resource.getValue().getAggregateType()) ||
extendedResources.get(resource.getKey()).getValue() < resource.getValue().getValue()) {
return false;
}
}
return true;
}
return false;
} }
@Override @Override
public int compareTo(@Nonnull ResourceProfile other) { public int compareTo(@Nonnull ResourceProfile other) {
int cmp1 = Integer.compare(this.getMemoryInMB(), other.getMemoryInMB()); int cmp = Integer.compare(this.getMemoryInMB(), other.getMemoryInMB());
int cmp2 = Double.compare(this.cpuCores, other.cpuCores); if (cmp == 0) {
return (cmp1 != 0) ? cmp1 : cmp2; cmp = Double.compare(this.cpuCores, other.cpuCores);
}
if (cmp == 0) {
Iterator<Map.Entry<String, ResourceSpec.Resource>> thisIterator = extendedResources.entrySet().iterator();
Iterator<Map.Entry<String, ResourceSpec.Resource>> otherIterator = other.extendedResources.entrySet().iterator();
while (thisIterator.hasNext() && otherIterator.hasNext()) {
Map.Entry<String, ResourceSpec.Resource> thisResource = thisIterator.next();
Map.Entry<String, ResourceSpec.Resource> otherResource = otherIterator.next();
if ((cmp = otherResource.getKey().compareTo(thisResource.getKey())) != 0) {
return cmp;
}
if (!otherResource.getValue().getAggregateType().equals(thisResource.getValue().getAggregateType())) {
return 1;
}
if ((cmp = Double.compare(thisResource.getValue().getValue(), otherResource.getValue().getValue())) != 0) {
return cmp;
}
}
if (thisIterator.hasNext()) {
return 1;
}
if (otherIterator.hasNext()) {
return -1;
}
}
return cmp;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
...@@ -169,6 +240,7 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -169,6 +240,7 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
result = 31 * result + heapMemoryInMB; result = 31 * result + heapMemoryInMB;
result = 31 * result + directMemoryInMB; result = 31 * result + directMemoryInMB;
result = 31 * result + nativeMemoryInMB; result = 31 * result + nativeMemoryInMB;
result = 31 * result + extendedResources.hashCode();
return result; return result;
} }
...@@ -181,20 +253,40 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile ...@@ -181,20 +253,40 @@ public class ResourceProfile implements Serializable, Comparable<ResourceProfile
ResourceProfile that = (ResourceProfile) obj; ResourceProfile that = (ResourceProfile) obj;
return this.cpuCores == that.cpuCores && return this.cpuCores == that.cpuCores &&
this.heapMemoryInMB == that.heapMemoryInMB && this.heapMemoryInMB == that.heapMemoryInMB &&
this.directMemoryInMB == that.directMemoryInMB; this.directMemoryInMB == that.directMemoryInMB &&
} Objects.equals(extendedResources, that.extendedResources);
else {
return false;
} }
return false;
} }
@Override @Override
public String toString() { public String toString() {
String resourceStr = "";
for (Map.Entry<String, ResourceSpec.Resource> resource : extendedResources.entrySet()) {
resourceStr += ", " + resource.getKey() + "=" + resource.getValue();
}
return "ResourceProfile{" + return "ResourceProfile{" +
"cpuCores=" + cpuCores + "cpuCores=" + cpuCores +
", heapMemoryInMB=" + heapMemoryInMB + ", heapMemoryInMB=" + heapMemoryInMB +
", directMemoryInMB=" + directMemoryInMB + ", directMemoryInMB=" + directMemoryInMB +
", nativeMemoryInMB=" + nativeMemoryInMB + ", nativeMemoryInMB=" + nativeMemoryInMB + resourceStr +
'}'; '}';
} }
public static ResourceProfile fromResourceSpec(
ResourceSpec resourceSpec) {
Map<String, ResourceSpec.Resource> extendResource = new HashMap<>(1);
double gpu = resourceSpec.getGPUResource();
if (gpu > 0) {
extendResource.put(ResourceSpec.GPU_NAME, new ResourceSpec.GPUResource(gpu));
}
ResourceProfile resourceProfile = new ResourceProfile(
resourceSpec.getCpuCores(),
resourceSpec.getHeapMemory(),
resourceSpec.getDirectMemory(),
resourceSpec.getNativeMemory(),
extendResource
);
return resourceProfile;
}
} }
...@@ -18,8 +18,12 @@ ...@@ -18,8 +18,12 @@
package org.apache.flink.runtime.clusterframework.types; package org.apache.flink.runtime.clusterframework.types;
import org.apache.flink.api.common.operators.ResourceSpec;
import org.junit.Test; import org.junit.Test;
import java.util.Collections;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
...@@ -27,10 +31,10 @@ public class ResourceProfileTest { ...@@ -27,10 +31,10 @@ public class ResourceProfileTest {
@Test @Test
public void testMatchRequirement() throws Exception { public void testMatchRequirement() throws Exception {
ResourceProfile rp1 = new ResourceProfile(1.0, 100, 100, 100); ResourceProfile rp1 = new ResourceProfile(1.0, 100, 100, 100, Collections.EMPTY_MAP);
ResourceProfile rp2 = new ResourceProfile(1.0, 200, 200, 200); ResourceProfile rp2 = new ResourceProfile(1.0, 200, 200, 200, Collections.EMPTY_MAP);
ResourceProfile rp3 = new ResourceProfile(2.0, 100, 100, 100); ResourceProfile rp3 = new ResourceProfile(2.0, 100, 100, 100, Collections.EMPTY_MAP);
ResourceProfile rp4 = new ResourceProfile(2.0, 200, 200, 200); ResourceProfile rp4 = new ResourceProfile(2.0, 200, 200, 200, Collections.EMPTY_MAP);
assertFalse(rp1.isMatching(rp2)); assertFalse(rp1.isMatching(rp2));
assertTrue(rp2.isMatching(rp1)); assertTrue(rp2.isMatching(rp1));
...@@ -45,10 +49,98 @@ public class ResourceProfileTest { ...@@ -45,10 +49,98 @@ public class ResourceProfileTest {
assertTrue(rp4.isMatching(rp2)); assertTrue(rp4.isMatching(rp2));
assertTrue(rp4.isMatching(rp3)); assertTrue(rp4.isMatching(rp3));
assertTrue(rp4.isMatching(rp4)); assertTrue(rp4.isMatching(rp4));
ResourceSpec rs1 = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(2.2).
build();
ResourceSpec rs2 = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(1.1).
build();
assertFalse(rp1.isMatching(ResourceProfile.fromResourceSpec(rs1)));
assertTrue(ResourceProfile.fromResourceSpec(rs1).isMatching(ResourceProfile.fromResourceSpec(rs2)));
assertFalse(ResourceProfile.fromResourceSpec(rs2).isMatching(ResourceProfile.fromResourceSpec(rs1)));
} }
@Test @Test
public void testUnknownMatchesUnknown() { public void testUnknownMatchesUnknown() {
assertTrue(ResourceProfile.UNKNOWN.isMatching(ResourceProfile.UNKNOWN)); assertTrue(ResourceProfile.UNKNOWN.isMatching(ResourceProfile.UNKNOWN));
} }
@Test
public void testEquals() throws Exception {
ResourceSpec rs1 = ResourceSpec.newBuilder().setCpuCores(1.0).setHeapMemoryInMB(100).build();
ResourceSpec rs2 = ResourceSpec.newBuilder().setCpuCores(1.0).setHeapMemoryInMB(100).build();
assertTrue(ResourceProfile.fromResourceSpec(rs1).equals(ResourceProfile.fromResourceSpec(rs2)));
ResourceSpec rs3 = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(2.2).
build();
ResourceSpec rs4 = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(1.1).
build();
assertFalse(ResourceProfile.fromResourceSpec(rs3).equals(ResourceProfile.fromResourceSpec(rs4)));
ResourceSpec rs5 = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(2.2).
build();
assertTrue(ResourceProfile.fromResourceSpec(rs3).equals(ResourceProfile.fromResourceSpec(rs5)));
}
@Test
public void testCompareTo() throws Exception {
ResourceSpec rs1 = ResourceSpec.newBuilder().setCpuCores(1.0).setHeapMemoryInMB(100).build();
ResourceSpec rs2 = ResourceSpec.newBuilder().setCpuCores(1.0).setHeapMemoryInMB(100).build();
assertEquals(0, ResourceProfile.fromResourceSpec(rs1).compareTo(ResourceProfile.fromResourceSpec(rs2)));
ResourceSpec rs3 = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(2.2).
build();
assertEquals(-1, ResourceProfile.fromResourceSpec(rs1).compareTo(ResourceProfile.fromResourceSpec(rs3)));
assertEquals(1, ResourceProfile.fromResourceSpec(rs3).compareTo(ResourceProfile.fromResourceSpec(rs1)));
ResourceSpec rs4 = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(1.1).
build();
assertEquals(1, ResourceProfile.fromResourceSpec(rs3).compareTo(ResourceProfile.fromResourceSpec(rs4)));
assertEquals(-1, ResourceProfile.fromResourceSpec(rs4).compareTo(ResourceProfile.fromResourceSpec(rs3)));
ResourceSpec rs5 = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(2.2).
build();
assertEquals(0, ResourceProfile.fromResourceSpec(rs3).compareTo(ResourceProfile.fromResourceSpec(rs5)));
}
@Test
public void testGet() throws Exception {
ResourceSpec rs = ResourceSpec.newBuilder().
setCpuCores(1.0).
setHeapMemoryInMB(100).
setGPUResource(1.6).
build();
ResourceProfile rp = ResourceProfile.fromResourceSpec(rs);
assertEquals(1.0, rp.getCpuCores(), 0.000001);
assertEquals(100, rp.getMemoryInMB());
assertEquals(100, rp.getOperatorsMemoryInMB());
assertEquals(1.6, rp.getExtendedResources().get(ResourceSpec.GPU_NAME).getValue(), 0.000001);
}
} }
...@@ -77,6 +77,7 @@ import org.slf4j.LoggerFactory; ...@@ -77,6 +77,7 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.File; import java.io.File;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
...@@ -346,7 +347,7 @@ public class YarnResourceManagerTest extends TestLogger { ...@@ -346,7 +347,7 @@ public class YarnResourceManagerTest extends TestLogger {
final SlotReport slotReport = new SlotReport( final SlotReport slotReport = new SlotReport(
new SlotStatus( new SlotStatus(
new SlotID(taskManagerResourceId, 1), new SlotID(taskManagerResourceId, 1),
new ResourceProfile(10, 1, 1, 1))); new ResourceProfile(10, 1, 1, 1, Collections.emptyMap())));
CompletableFuture<Integer> numberRegisteredSlotsFuture = rmGateway CompletableFuture<Integer> numberRegisteredSlotsFuture = rmGateway
.registerTaskExecutor( .registerTaskExecutor(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册