StartAppAttemptTransition(详见6)

Hadoop 2.7.6中StartAppAttemptTransition解析
本文详细介绍了在Hadoop 2.7.6版本中,StartAppAttemptTransition如何处理APP_ACCEPTED事件,使得RMApp状态从SUBMITTED转变为ACCEPTED。内容包括创建RMAppAttempt,并触发RMAppStartAttemptEvent,进一步解析事件处理器RMAppAttemptImpl的角色。
StartAppAttemptTransition(基于hadoop 2.7.6)

StartAppAttemptTransition是对RMAppEventType.APP_ACCEPTED事件的转换处理,转换处理后RMApp状态由SUBMITTED变为ACCEPTED.

主要逻辑:
1.创建RMAppAttempt,RMAppImpl会维护一个
<ApplicationAttemptId, RMAppAttempt>的映射表
2.触发RMAppStartAttemptEvent (RMAppAttemptEventType.START)事件,该事件的处理器是AttemptStartedTransition.

private static final class StartAppAttemptTransition extends RMAppTransition {
    @Override
    public void transition(RMAppImpl app, RMAppEvent event) {
      app.createAndStartNewAttempt(false);
    };
  }
private void
      createAndStartNewAttempt(boolean transferStateFromPreviousAttempt) {
    createNewAttempt();
    /**
    *触发RMAppAttemptEventType.START事件
    */
    handler.handle(new RMAppStartAttemptEvent(currentAttempt.getAppAttemptId(),
      transferStateFromPreviousAttempt));
  }
private void createNewAttempt() {
    ApplicationAttemptId appAttemptId =
        ApplicationAttemptId.newInstance(applicationId, attempts.size() + 1);
    RMAppAttempt attempt =
        new RMAppAttemptImpl(appAttemptId, rmContext, scheduler, masterService,
          submissionContext, conf,
          /**
           * 	这里有尝试次数限制
           */
          maxAppAttempts == (getNumFailedAppAttempts() + 1), amReq);
          /**
          * 记录在attempts映射表中
          */
    attempts.put(appAttemptId, attempt);
    currentAttempt = attempt;
  }

想查找RMAppAttemptEventType类型的处理器是哪个,到ResourceManager中查找为该事件类型注册的调度器。

rmDispatcher.register(RMAppAttemptEventType.class,
          new ApplicationAttemptEventDispatcher(rmContext));
@Private
  public static final class ApplicationAttemptEventDispatcher implements
      EventHandler<RMAppAttemptEvent> {
    private final RMContext rmContext;
    public ApplicationAttemptEventDispatcher(RMContext rmContext) {
      this.rmContext = rmContext;
    }
    
    @Override
    public void handle(RMAppAttemptEvent event) {
      ApplicationAttemptId appAttemptID =                                       event.getApplicationAttemptId();
      ApplicationId appAttemptId = appAttemptID.getApplicationId();
      RMApp rmApp = this.rmContext.getRMApps().get(appAttemptId);
      if (rmApp != null) {
        RMAppAttempt rmAppAttempt = rmApp.getRMAppAttempt(appAttemptID);
        if (rmAppAttempt != null) {
          try {
            rmAppAttempt.handle(event);
          } catch (Throwable t) {
            LOG.error("Error in handling event type " + event.getType()
                + " for applicationAttempt " + appAttemptId, t);
          }
        }
      }
    }
  }

从ApplicationAttemptEventDispatcher的handle()方法可以看出,事件处理器是RMAppAttemptImpl.

### Q31格式技术详解 Q31是一种定点数表示格式,通常用于32位有符号整数中。Q31格式的数值由1位符号位31位小数部分组成,数值范围为[-1, 1)。这种格式广泛应用于嵌入式系统数字信号处理(DSP)领域,尤其是在没有硬件浮点运算单元(FPU)的处理器上,以实现高效的定点数运算[^1]。 #### 数据表示 Q31格式的数值可以表示为: ``` Value = (-1)^S * (Integer_Part + Fractional_Part) / 2^31 ``` 其中: - `S` 是符号位,0表示正数,1表示负数。 - `Integer_Part` 是整数部分,仅占1位(符号位),因此Q31格式的整数部分只能是0或1。 - `Fractional_Part` 是小数部分,占31位。 Q31格式的数值范围为: - 最大正数:`0x7FFFFFFF` ≈ 0.9999999995343397 - 最小负数:`0x80000000` = -1.0 #### 精度特性 Q31格式的精度由小数部分的31位决定,其最小分辨率为: ``` Resolution = 1 / 2^31 ≈ 4.6566128730773926e-10 ``` 这意味着Q31格式可以表示非常精细的小数,但由于整数部分只能为0或1,因此它适用于表示范围在[-1, 1)内的数值[^1]。 #### 算术运算 Q31格式的算术运算需要考虑溢出舍入问题。以下是一些常见的Q31算术操作: ##### 加法 两个Q31格式的数可以直接相加,但需要注意溢出问题。例如: ```c q31_t a = 0x40000000; // 0.25 q31_t b = 0x20000000; // 0.125 q31_t result = a + b; // 0.375 ``` ##### 乘法 Q31格式的乘法需要将结果右移31位以保持Q31格式。例如: ```c q31_t a = 0x40000000; // 0.25 q31_t b = 0x20000000; // 0.125 int64_t temp = (int64_t)a * b; // 乘法结果为64位 q31_t result = (q31_t)(temp >> 31); // 0.03125 ``` ##### 移位操作 移位操作可用于调整Q格式的精度。例如,将Q31值乘以2可以表示为左移1位: ```c q31_t a = 0x40000000; // 0.25 q31_t result = a << 1; // 0.5 ``` #### 应用场景 Q31格式广泛应用于嵌入式系统的数字信号处理任务,如音频处理、滤波器设计控制算法。ARM CMSIS DSP库提供了针对Q31格式的优化函数,例如`arm_sqrt_q31`用于计算Q31格式的平方根。这些函数在资源受限的环境中具有较高的效率。 #### 与其他Q格式的比较 Q31格式与其他Q格式(如Q15、Q7)的主要区别在于精度表示范围: - **Q15**:1位符号位 + 15位小数部分,数值范围为[-1, 1),最小分辨率为1/2^15 ≈ 3.0517578125e-5。 - **Q7**:1位符号位 + 7位小数部分,数值范围为[-1, 1),最小分辨率为1/2^7 = 0.0078125。 - **Q31**:1位符号位 + 31位小数部分,数值范围为[-1, 1),最小分辨率为1/2^31 ≈ 4.6566128730773926e-10。 Q31格式的精度最高,但其表示范围有限,适用于需要高精度但数值范围较小的场景。 #### 与浮点数的比较 与浮点数相比,Q31格式具有以下特点: - **优势**:在没有FPU的处理器上,Q31格式的运算速度更快,内存占用更小。 - **劣势**:Q31格式的动态范围较小,且需要手动处理溢出舍入问题。 例如,将Q31格式转换为浮点数可以通过以下方式实现: ```c float q31_to_float(q31_t value) { return (float)value / 2147483648.0f; // 2^31 } ``` #### 注意事项 使用Q31格式时需要注意以下问题: 1. **溢出**:Q31格式的范围为[-1, 1),因此在进行加法或乘法运算时需要避免溢出。 2. **精度损失**:由于Q31格式的精度有限,多次运算可能会导致精度损失。 3. **标准化**:在将浮点数转换为Q31格式时,需要进行标准化处理以确保数值在合法范围内。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值