Dibuja con tu CPU

289

Me encontré con un artículo donde los estudiantes usaban el tráfico de red para dibujar su universidad en el gráfico IPv6 del país . [imagen]

Su objetivo es simple de decir, pero difícil de implementar. Dibuje el texto CORREO (ya que es una de las pocas palabras que se puede leer en un gráfico 1D) en el gráfico de la CPU.

Debería verse más o menos así:

Resultado

Elaborando un poco más sobre lo que califica:

  • El código no necesita ser multiplataforma (por lo que no necesitará API desconocidas para tratar).
  • Puede capturarlo en cualquier utilidad general de uso de CPU que tenga.
  • El gráfico se ve un poco peor en una máquina diferente: esta vez confío en ti.
  • El% de uso de CPU base debe ser continuo, por lo que si genera una onda aleatoria y resalta algo que se parece a la palabra CORREO, obviamente es trampa.
  • Puede elegir la carga máxima para usar, pero tiene que ser lo suficientemente sustancial como para verla claramente.
  • Debe seguir la linealidad del ejemplo. (Para M se ve así:% base, luego aumento repentino al máximo especificado, caer gradualmente a un% más bajo, volver a subir al máximo y caer repentinamente al% base nuevamente.)
  • Si es ilegible, los votantes lo notarán después de todo.

Se aplican lagunas estándar. ¡Publica las imágenes también!

bebe
fuente
99
Ya no veo una razón para la votación cerrada. Personalmente, considero que es un desafío divertido, aunque un poco específico del sistema.
seequ
66
El problema que veo con el código de golf es juzgar cuán legible es lo suficientemente legible. Si puede pensar en una forma de especificar eso objetivamente, eso mejoraría en gran medida el desafío, ¡pero es una buena idea de todos modos!
Martin Ender
3
en realidad es lo mismo que tu imagen, pero te garantizo que si no lo expresas en palabras, la gente interpretará "dibujar CORREO" de manera muy liberal.
Martin Ender
33
+1, es tan absurdo que casi me muero de risa ... "esto es una locura ..." "una locura ... ¡ESTO ES CODEGOLF !"
vaxquis
55
Esta es una pregunta increíble . Desearía ser lo suficientemente inteligente como para participar. Eso realmente no importa, estoy interesado en las soluciones creativas de otras personas: P
Chris Cirefice

Respuestas:

117

Pitón, 143

from time import*
while 1:
 sleep((ord('00012345654321000~~~D:6300036:D~~~000~~~000DDDD~~~~~'[int(time())%52])-48)*0.001);x=10**5
 while x:x-=1

Cada carácter de la cadena corresponde a un segundo de actividad, desde el carácter ASCII 0(carga máxima) hasta ~(carga muy ligera). El programa se ejecuta en un ciclo sincronizado en el tiempo, por lo que puede ejecutar varias instancias para obtener mejores resultados.

Utilicé Python 2.7.6 en OS X con un Intel Core i7, pero debería funcionar en otras computadoras con un poco de ajuste (ajuste 0.001). La captura de pantalla a continuación se tomó con una importante actividad de fondo.

CORREO

Actualización: pude producir un gráfico más claro time()/10y con una frecuencia de actualización más baja:

CORREO

Y finalmente, aquí hay una versión más golfizada ( 123 bytes ) y su resultado :

from time import*
while 1:
 sleep((ord('002464200~~A5005A~~00~~00DDD~~'[int(time()/2)%30])-48)*0.001);x=10**5
 while x:x-=1
grc
fuente
250

Python, 358 281 268 221 194 bytes

Monocromo es tan el año pasado. ¡Esto utiliza múltiples procesos y syscalls para lograr gráficos de CPU de dos colores !

import os,time
A='%-99o'%int('t12q2lxqkap48euoej9429cstbnazl63ubyryteo49u',36)
for i in'0123456':
 t=os.fork()
 while t<1:T=int(time.time())%50;(time.sleep,(id,os.urandom)[i<A[T+49]])[i<A[T]](1)

Salida del Monitor de actividad (OS X 10.9):

Gráfico de carga de la CPU del monitor de actividad Gráfico de historial de CPU del monitor de actividad

Se repite en el gráfico del historial de la CPU

Salida de MenuMeters:

Salida de MenuMeters

Todas las salidas se generaron con una velocidad de actualización de 1s. No se estaban ejecutando tareas importantes en segundo plano, aunque esta salida supera con bastante facilidad cualquier tarea de CPU de un solo subproceso.

Este código asume que tienes 8 núcleos. Debería ser bastante fácil de modificar para menos / más. Es portátil para sistemas Linux / UNIX (aunque solo se ha probado en OS X), y debe producir la misma salida de dos colores para cualquier monitor de CPU que pueda distinguir el tiempo de CPU del usuario del sistema.

Esencialmente, esto funciona al desechar siete procesos, cada uno de los cuales elegirá pasar 1 segundo durmiendo, girando en modo de usuario o girando el núcleo. El giro en el modo kernel se logra solicitando grandes cantidades de datos /dev/urandom, lo que obliga al controlador /dev/urandoma invertir una gran cantidad de ciclos de CPU del "sistema".

EDITADO [21/07]: se acortó significativamente al usar en fork()lugar de multiprocessing.Process( /dev/urandomsolo funciona en sistemas * NIX de todos modos, por lo que esto no reduce la portabilidad). Sin embargo, tenga en cuenta que el programa ahora genera tareas en segundo plano ; Puede que tenga que killall Python(o similar) para deshacerse de los consumidores de CPU.


No pude resistirme a implementar algunas cartas más. Tengo 16 letras, más algunos símbolos:

~ /._ PIN ANCHO ... ... VY

El alfabeto completo es "ACDFHILMNOPTUVWY", con los símbolos "._ ~ / \". Probablemente hay muchos más personajes que se pueden representar.

Código completamente sin golf para las letras adicionales:

from time import*
from multiprocessing import*

chars6 = {
'A': ('123456654321',
      '000123321000'),
'C': ('344556666666',
      '321110000000'),
'D': ('666666655443',
      '000000011123'),
'F': ('66666666666666',
      '00002222244444'),
'H': ('666664444466666',
      '000002222200000'),
'I': ('66666',
      '00000'),
'L': ('666662222222',
      '000000000000'),
'M': ('6665544334455666',
      '0004321001234000'),
'N': ('66665544336666',
      '00003322110000'),
'O': ('3445556666555443',
      '3221110000111223'),
'P': ('666666666555',
      '000003333444'),
'T': ('777776666677777',
      '444440000044444'),
'U': ('6666322236666',
      '4211000001124'),
'V': ('66654322345666',
      '33321000012333'),
'W': ('66542466424566',
      '43210133101234'),
'Y': ('66665433456666',
      '44333000033344'),
'_': ('1111111111',
      '0000000000'),
' ': ('000',
      '000'),
'.': ('12221',
      '10001'),
'~': ('44445544334444',
      '11223322112233'),
'/': ('2234566',
      '0012344'),
'\\': ('6654322',
       '4432100'),
}

s = 'ANCHOVY '
A = '000'.join(chars6[t][0] for t in s)
B = '000'.join(chars6[t][1] for t in s)

t=time()
f=open('/dev/urandom')
def F(n):
 while 1:T=int(time()-t)%len(A);[sleep,[].count,lambda x:f.read(4**9)][(n<int(A[T]))+(n<int(B[T]))](1)
for i in range(7):Process(target=F,args=(i,)).start()
F(7)
nneonneo
fuente
34
+1 para dar más definición a las letras con 2 colores
DustinDavis
44
Y +1 para la creación de cartas con
tablas
1
De hecho, la A podría representarse correctamente (con un agujero) con 4 hilos. Sin embargo, tendría que configurar algunos colores de monitor de CPU para que coincidan.
Ruslan
@Ruslan: ¿En qué monitor de CPU estás pensando? Mi monitor muestra solo un gráfico agregado, con 0 <= sistema <= usuario <= 100 en cada punto (lo que hace que los "agujeros" sean imposibles AFAIK).
nneonneo
1
@nneonneo Me refiero a monitores similares a los tuyos. Mira esta foto . Aquí, si cambiamos de azul a verde y rojo y de púrpura a blanco, obtendremos una bonita "A" con agujeros.
Ruslan
133

C (Intel Core Duo + OS X / Darwin), 248 bytes

#include <unistd.h>
#include <mach/mach_time.h>
#define M mach_absolute_time()
main(){char*s="JJJIHGFGHIJJJ@BDFHJJJHFDB@JJJJ@JJJJBBBBBBB";uint64_t i,t,y=1;for(;*s;s++){
for(i=40;i;i--){for(t=M+(*s&15)*9090909;t>M;)y*=7;usleep((11-(*s&15))*9091);}}}

Este código es tan portátil como la Gran Pirámide de Keops. Lo siento por eso. Los valores devueltos mach_absolute_time()dependen del hardware, pero en mi máquina el valor aumenta aproximadamente una vez por nanosegundo.

Aquí está el resultado:

La palabra "CORREO" se muestra en mi gráfico de historial de CPU

Hay dos gráficos porque el procesador tiene dos núcleos. Establecí la carga máxima de CPU en aproximadamente el 90% porque el proceso puede cambiar entre núcleos cada vez que llamo usleep(). Con una carga del 100%, el proceso se encadena a un núcleo y los resultados son ilegibles ( ver esto, por ejemplo )

ossifrage aprensivo
fuente
1
¡Buen trabajo! Esto se ve muy interesante. ¿Podría por favor publicar una pequeña explicación del código? :)
duci9y
1
Veo llaves. ¿Por qué hay llaves en los bucles for? puedes poner usleep en el segundo bloque del último bucle. Creo que puedes jugar al golf un poco más fácilmente.
bebe
¿No podría poner la declaración y la inicialización de las uint64_tvariables en el encabezado del siguiente forbucle?
Joey
74
+1: "Este código es tan portátil como la Gran Pirámide de Keops"
Uwe Keim
@ No, las variables C deben declararse al comienzo de un bloque. ponerlo en el bloque de inicialización de for arrojará un error. por supuesto, solo se aplica a <C99
bebe
102

Ruby, 150 caracteres.

a=(0..15).map{|i|[0.9-3*i*=0.02,i]}
[9,*a[0,11],*(z=a.reverse)[5,11],11,*z,*a,2,11,6,*[0.2]*9].map{|x,y|c=Time.now
1until Time.now-c>x/3
sleep y||x%3}

Esto no es tan corto hasta ahora, pero en mi opinión el resultado es bastante bueno, así que pensé que publicaría esto de todos modos. Al igual que con la mayoría de las otras soluciones, es posible que deba fijar el proceso de Ruby en un núcleo determinado con el prefijo taskset -c $core.

El código es una combinación simple de girar / dormir durante una cierta cantidad de tiempo, lo que debería hacerlo algo portátil. Los gradientes suaves se crean variando la relación del tiempo de centrifugado / reposo.

CORREO escrito monitor de la CPU

Bajar la frecuencia de muestreo de la CPU hace que los bordes se vean un poco mejor:

Menor frecuencia de muestreo

Al agregar algunas letras más al alfabeto ( AILMNUVWson algo reconocibles), también podemos escribir algunas otras palabras:

Mamá, Fauces, Villano

Estas imágenes se generaron con el siguiente código:

def gradient num_samples, direction, base = 0.3, increment = 0.02, scale = 1
    range = [*0..num_samples]

    samples = case direction
        when :up then range.reverse
        when :down then range
        when :updown then range.reverse + range
        when :downup then range + range.reverse
    end

    samples.map{|i|
        i *= increment
        [base - scale * i, i]
    }
end

# letters are defined as a series of pairs of (spin-time, sleep-time)
# with the time in seconds
THIN_A = gradient(15, :updown, 0.2, 0.2/15)
A = gradient(15, :updown)
I = 2,0
L = 1.5,0, [[0.1,0.2]]*9
M = 2,0, gradient(9, :downup), 2,0
N = 1,0, gradient(9, :down), 2,0
U = 1,0, gradient(9, :downup, 0.1, 0.03, 0.1), 1,0
V = 0.5,0, gradient(12, :downup, 0.25, 0.02), 0.5,0
W = 0.5,0, [gradient(12, :downup, 0.25, 0.02)]*2, 0.5,0

[A,I,L,M,N,U,V,W].map{|i|
    # add 2 second pause after each letter
    i + [0,2]
}.flatten.each_slice(2){|x,y|
    # spin, then sleep
    c = Time.now
    1 until Time.now-c > x
    sleep y
}

Las palabras que se pueden escribir con las letras implementadas se pueden encontrar con

grep -E '^[aijlmnuvw]+$' /usr/share/dict/words 
Ventero
fuente
44
¡+1 para la extensión en más palabras!
Chris Cirefice
Podrías haber hecho la palabra "aluminio".
Oliver Daugherty-Long
@ OliverDaugherty-Long aluminio *
TuxCrafting
1
@ TùxCräftîñg Aluminio es una ortografía variante que tiene una letra extra, y es la palabra más larga que se me ocurre que funciona.
Oliver Daugherty-Long
48

Python, el procesador Intel Pentium 4 3.0 GHz, 180 166 145 141 138 bytes

Llamada con taskset -c 0 python cpu_graph_drawer.py.

taskset es necesario para restringir el proceso para usar solo una CPU / núcleo (hyperthreading en mi caso).

from time import*;c=clock
a=[(3,.8),(3,5),(4,5),(1.3,5),(1.3,0)]
a.extend([(.1,.2)]*10)
for x,y in a:
    t=c()
    while c()-t<x:pass
    sleep(y)

El resultado no es tan bueno. Este con el conjunto de tareas -c 1

usuario80551
fuente
99
Me encantaría ver esto con un monitor de CPU que no suaviza las curvas ...
Szabolcs
1
Yo también, pero no tengo ganas de escribir un gráfico de uso de CPU conky y gnome-system-monitores lo único que sé. ¿Tienes alguna alternativa que se ejecute en LMDE Cinnamon?
user80551
Active "Dibujar CPU como gráfico de área apilada" y configure todos los colores en negro.
Tejas Kale
@TejasKale Las líneas seguirían siendo curvas.
user80551
FYI: puedes jugar un montón de caracteres usando en a=[...]+[(.1,.2)]*10lugar de .extend.
nneonneo
46

Java 8, 482 caracteres

Cada carácter en la cadena significa número de hilos, que serán utilizados. Imagen tomada en Intel Core i3 (2 núcleos / 4 hilos).

resultado

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Mail{
public static void main(String[] args) throws InterruptedException{
Thread.sleep(15000);
for(char c:"123432234321000012343210000444000044441111111".toCharArray()){
ExecutorService executorService = Executors.newScheduledThreadPool(4);
for(int i=1;i<c-48;i++)executorService.execute(()->{while(!Thread.interrupted());});
Thread.sleep(1500);
executorService.shutdownNow();
}}}

Editar : versión más golfizada (322 caracteres), misma funcionalidad:

import java.util.concurrent.*;
class M{
public static void main(String[]a)throws Exception{
for(int c:"123432234321000012343210000444000044441111111".toCharArray()){
ExecutorService s=Executors.newFixedThreadPool(4);
while(c>48){c--;s.execute(()->{while(!Thread.interrupted());});}
Thread.sleep(1500);
s.shutdownNow();
}}}
Tomáš Dvořák
fuente
1
Hay un signo menor que se interpretó como HTML y estropeó el formato.
David Conrad
@ValekHalfHeart las siguientes dos líneas deberían explicarlo. El ejecutor es un hilo (administrador de tareas asíncrono) que ejecuta tareas (aquí bucles) hasta la interrupción. Después de crearlo, el subproceso principal espera 1,5 segundos y luego interrumpe todas las tareas.
PTwr
45
Al abrir Eclipse, mi gráfico de CPU escribió "Protocolo simple de transferencia de correo".
lolesque
21

C, 78 bytes

Nunca dijiste que no podíamos aceptar las aportaciones de los usuarios, así que ...

#include <unistd.h>
int main(){int x=0;for(;x<1<<26;++x);read(0,&x,1);main();}

Este programa lee desde el estándar y cada vez que lee un carácter, ejecuta un desperdicio de CPU gratuito para el bucle, luego llama a main nuevamente. Usted controla la cantidad de tiempo de CPU que usa enviando la tecla enter a diferentes velocidades.

Ejecuté esto en un Intel i3 4130T, que es un procesador razonablemente nuevo. Pero su millaje puede variar, si está usando más o menos tiempo de CPU de lo que es práctico para usted, intente jugar con la cantidad de cambio en el ciclo de retraso.

Mi programa es increíble porque:

  • es principalmente multiplataforma, debería funcionar con muy poco violín en cualquier * nix
  • derrota la pregunta
  • gran juego final

Después de algunos intentos, produje un gráfico que se veía así:Gráfico de la CPU

Wug
fuente
Ayuda a restringirlo a un núcleo de CPU con conjunto de tareas, a.la. taskset -c 1 [file]
Wug
2
No veo nada en los requisitos del problema que diga que nuestras presentaciones se invocarán comoyes | [program]
Wug
1
"Gran juego final" me hizo reír mucho. +1
Christoph
1
Sin embargo, esta respuesta es demasiado buena, ¡las lagunas sean condenadas xD!
Urna mágica de pulpo