Go: cmd/compile: testing/quick misbehaves on Nexus 9 linux/arm64

Criado em 31 mar. 2017  ·  3Comentários  ·  Fonte: golang/go

O seletor int64 do testing/quick é escrito para retornar valores no intervalo [-2⁶²,2⁶²).
Isso é um erro; corrigindo que é #19808.

Mas o código deve ser executado como escrito, e ainda no Nexus 9 de @ dr2chase
executando uma cadeia de ferramentas linux/arm64 construída a partir de uma cadeia de ferramentas android/arm64
compilado de outro lugar, empiricamente gera valores fora
esse intervalo. (Isso ajudou a encontrar o nº 19807.)

Usando uma cadeia de ferramentas linux/arm64 construída a partir de uma cadeia de ferramentas linux/arm64
a compilação cruzada de outro lugar em um Odroid funciona corretamente.

Antes de corrigir o teste/rápido para gerar o intervalo completo, devemos descobrir
descobrir por que o código atual gera valores fora do intervalo mais estreito
nesta configuração.

math/rand's (*Rand).Int63 diz:

return r.src.Int63()

e (*rngSource).Int63 diz:

return int64(rng.Uint64() & _MASK)

Onde:

const (
    _MAX  = 1 << 63
    _MASK = _MAX - 1
)

e, em seguida, a função randInt64 do testing/quick faz:

return rand.Int63() - 1<<62

Portanto, ou o & _MASK ou o - 1<<62 não está fazendo seu trabalho.

Pode ser que o hardware do Nexus 9 ARM64 esteja com bugs.
Pode ser que a cadeia de ferramentas android/arm64 sendo usada para
bootstrap no Nexus 9 é buggy, fazendo com que o compilado nativamente
cadeia de ferramentas linux/arm64 seja com bugs, fazendo com que o teste/rápido
código para gerar valores inesperados. Nós não sabemos.

FrozenDueToAge

Comentários muito úteis

O seguinte programa C se comporta mal no sistema problemático.

#include <stdio.h>

typedef unsigned long long uvlong;

uvlong f() { return ~0ull; }
uvlong g() { return (f() << 1) >> 1; }

int main() {
    for (int i = 0;; i++) {
        if ((long long)g() < 0) {
            printf("%d\n", i);
        }
    }
    return 0;
}

Após 20k-50k iterações, o loop começa a imprimir i em cada iteração.

Não é culpa de Go. Veremos sobre relatar isso em outro lugar.

Todos 3 comentários

CL https://golang.org/cl/39152 menciona esse problema.

O seguinte programa C se comporta mal no sistema problemático.

#include <stdio.h>

typedef unsigned long long uvlong;

uvlong f() { return ~0ull; }
uvlong g() { return (f() << 1) >> 1; }

int main() {
    for (int i = 0;; i++) {
        if ((long long)g() < 0) {
            printf("%d\n", i);
        }
    }
    return 0;
}

Após 20k-50k iterações, o loop começa a imprimir i em cada iteração.

Não é culpa de Go. Veremos sobre relatar isso em outro lugar.

CL https://golang.org/cl/39310 menciona esse problema.

Esta página foi útil?
0 / 5 - 0 avaliações