Рисовать с вашим процессором


289

Я наткнулся на статью, где студенты использовали сетевой трафик, чтобы нарисовать свой университет на графике IPv6 страны . [образ]

Ваша цель проста, но ее трудно реализовать. Нарисуйте текст MAIL (так как это одно из немногих слов, которые можно прочитать на одномерном графике) на графике ЦП.

Это должно выглядеть примерно так:

Результат

Разрабатывая немного больше о том, что соответствует:

  • Код не обязательно должен быть кроссплатформенным (поэтому вам не понадобятся неизвестные API для работы).
  • Вы можете записать его в любую общую утилиту использования процессора, которая у вас есть.
  • График выглядит немного хуже на другом компьютере: я доверяю вам на этот раз.
  • Базовое использование ЦП% должно быть непрерывным, поэтому, если вы генерируете случайную волну и выделяете что-то, похожее на слово MAIL, это, очевидно, обман.
  • Вы можете выбрать максимальную нагрузку для использования, но она должна быть достаточно значительной, чтобы четко ее увидеть.
  • Вы должны следовать линейности примера. (Для M это выглядит так: базовый%, затем внезапное увеличение до указанного максимума, постепенное падение до более низкого%, возврат к максимальному значению и внезапное падение до базового%.)
  • Если это нечитаемо, избиратели все же заметят.

Применяются стандартные лазейки. Опубликовать изображения тоже!


9
Я больше не вижу причин для закрытого голосования. Лично я считаю это забавным испытанием, хотя и немного специфичным для системы.
seequ

6
Проблема, которую я вижу в коде гольф, состоит в том, чтобы судить, насколько разборчиво достаточно разборчиво. Если вы можете придумать способ указать это объективно, это значительно улучшит задачу, но в любом случае это действительно хорошая идея!
Мартин Эндер

3
это действительно так же, как ваша картина, но я гарантирую вам, если вы не выразите это словами, люди будут очень свободно интерпретировать «рисовать ПОЧТУ».
Мартин Эндер

33
+1, это так абсурдно, что я чуть не засмеялся до смерти ... "это безумие ..." "безумие ... ЭТО КОДЕГОЛЬФ !!!"
vaxquis

5
Это чертовски крутой вопрос. Я хотел бы быть достаточно умным, чтобы участвовать. Это не имеет большого значения, меня интересуют креативные решения других людей: P
Крис Сирефице

Ответы:


117

Питон, 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

Каждый символ строки соответствует одной секунде активности, от символа ASCII 0(максимальная загрузка) до ~(очень легкая загрузка). Программа запускается по циклу с синхронизацией времени, поэтому вы можете запустить несколько экземпляров для получения лучших результатов.

Я использовал Python 2.7.6 на OS X с Intel Core i7, но он должен работать на других компьютерах с небольшой настройкой (настройте 0.001). Скриншот ниже был сделан со значительной фоновой активностью.

MAIL

Обновление - мне удалось создать более четкий график с time()/10более низкой частотой обновления:

MAIL

И, наконец, вот еще версия для гольфа ( 123 байта ) и ее результат :

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

250

Python, 358 281 268 221 194 байта

Монохромный так в прошлом году. Это использует несколько процессов и системных вызовов для получения двухцветных графиков ЦП!

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)

Вывод из Activity Monitor (OS X 10.9):

График загрузки процессора монитора активности График истории активности CPU монитора активности

Повторяется на графике истории процессора

Выход из MenuMeters:

Выход MenuMeters

Все выходные данные были созданы со скоростью обновления 1 с. Никаких значительных фоновых задач не выполнялось, хотя этот вывод довольно легко превосходит любую однопоточную задачу ЦП.

Этот код предполагает, что у вас есть 8 ядер. Это должно быть довольно легко изменить на меньшее / большее. Он переносим на системы Linux / UNIX (хотя он был протестирован только на OS X) и должен обеспечивать одинаковый двухцветный вывод для любого монитора ЦП, который может отличать время ЦП от пользователя.

По сути, это работает путем разветвления семи процессов, каждый из которых выберет потратить 1 секунду на сон, вращение в пользовательском режиме или вращение ядра. Вращение в режиме ядра достигается путем запроса больших объемов данных /dev/urandom, что заставляет драйвер при затратах /dev/urandomтратить много «системных» циклов ЦП.

РЕДАКТИРОВАНИЕ [07/21]: Значительно сокращено при использовании fork()вместо multiprocessing.Process/dev/urandomлюбом случае работает только на системах * NIX, поэтому это не уменьшает мобильность). Обратите внимание, что теперь программа порождает фоновые задачи; Возможно, вам придется killall Python(или подобное), чтобы избавиться от пожирателей процессора.


Я не мог удержаться от реализации еще нескольких писем. Я получил 16 букв плюс несколько символов:

~ /._ PIN Ancho ... ... В.Я.

Полный алфавит "ACDFHILMNOPTUVWY", с символами "._ ~ / \". Вероятно, есть гораздо больше символов, которые могут быть представлены.

Целиком код для дополнительных букв:

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)

34
+1 за придание буквам большей четкости, используя 2 цвета
DustinDavis

4
И +1 для создания письма на основе таблицы
GreenAsJade

1
Фактически, A может быть правильно отрисован (с отверстием) с 4-мя потоками. Должны были бы установить некоторые цвета монитора процессора, чтобы совпадать, хотя.
Руслан

@Ruslan: О каком мониторе процессора вы думаете? Мой монитор показывает только один агрегированный график, с 0 <= system <= user <= 100 в каждой точке (что делает «дыры» невозможными AFAIK).
nneonneo

1
@nneonneo Я имею в виду мониторы, похожие на ваши. Смотрите эту картинку . Здесь, если мы изменим синий на зеленый и красный и фиолетовый на белый, мы получим хорошую букву "А" с отверстиями.
Руслан

133

C (Intel Core Duo + OS X / Darwin), 248 байт

#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);}}}

Этот код примерно так же переносим, ​​как Великая пирамида Хеопса. Прости за это. Возвращаемые значения mach_absolute_time()зависят от аппаратного обеспечения, но на моем компьютере значение увеличивается примерно раз в наносекунду.

Вот результат:

Слово «MAIL» отображается в моем графике истории процессора

Есть два графика, потому что процессор имеет два ядра. Я установил максимальную загрузку процессора примерно на 90%, потому что процесс может переключаться между ядрами при каждом вызове usleep(). При 100% загрузке процесс связан с одним ядром, а результаты неразборчивы ( см., Например, это )


1
Отличная работа! Это выглядит очень интересно. Не могли бы вы опубликовать небольшое объяснение кода? :)
duci9y

1
Я вижу брекеты. почему в петлях для фигурных скобок? Вы можете поместить usleep во второй блок последнего цикла. Я думаю, что вы можете играть в гольф немного легче.
bebe

Не могли бы вы поместить объявление и инициализацию uint64_tпеременных в заголовок следующего forцикла?
Джои

74
+1: «Этот код примерно так же переносим, ​​как Великая пирамида Хеопса»
Уве Кейм,

@ Нет, переменные C должны быть объявлены в начале блока. помещение его в блок инициализации for приведет к ошибке. конечно это относится только к <C99
bebe

102

Рубин, 150 знаков

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}

Пока это не так уж и мало, но, на мой взгляд, результаты довольно хорошие, поэтому я решил, что все равно опубликую это. Как и в большинстве других решений, вам может потребоваться закрепить процесс Ruby на определенном ядре, добавив к нему префикс taskset -c $core.

Код представляет собой простую комбинацию вращения / сна в течение определенного времени, что должно сделать его несколько переносимым. Плавные градиенты создаются путем изменения соотношения времени вращения / сна.

ПОЧТОВЫЙ письменный монитор процессора

Снижение частоты дискретизации ЦП делает края немного лучше:

Более низкая частота дискретизации

Добавив еще несколько букв в алфавит ( AILMNUVWнесколько узнаваемых), мы также можем написать несколько других слов:

Мама, пасть, вилла

Эти изображения были сгенерированы с помощью следующего кода:

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
}

Слова, которые можно написать с помощью введенных букв, можно найти с помощью

grep -E '^[aijlmnuvw]+$' /usr/share/dict/words 

4
+1 за расширение на несколько слов!
Крис Cirefice

Вы могли бы сделать слово «алюминий».
Оливер Даугерти-Лонг,

@ OliverDaugherty-Long Алюминий *
TuxCrafting

1
@ TùxCräftîñg Алюминий - это вариант написания, в котором есть дополнительная буква, и это самое длинное слово, которое я могу вспомнить.
Оливер Даугерти-Лонг

48

Python, на Intel Pentium 4 3,0 ГГц, 180 166 145 141 138 байт

Позвони с taskset -c 0 python cpu_graph_drawer.py.

taskset необходимо ограничить процесс использованием только одного процессора / ядра (в моем случае гиперпоточность).

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)

Результат не так уж велик. Этот с набором задач -c 1


9
Я хотел бы видеть это с монитором процессора, который не сглаживает кривые ...
Szabolcs

1
Я тоже, но мне не хочется писать хитрый график использования ЦП, и gnome-system-monitorэто единственное, что я знаю. Есть какие-нибудь альтернативы, которые будут работать на LMDE Cinnamon?
user80551

Включите «Draw CPU as Stacked Area Table» и установите все цвета на черный.
Теджас Кале

@TejasKale Линии все еще будут изогнуты.
user80551

К вашему сведению: вы можете сыграть в гольф несколько символов, используя a=[...]+[(.1,.2)]*10вместо .extend.
nneonneo

46

Java 8, 482 символа

Каждый символ в строке означает количество потоков, которые будут использованы. Снимок сделан на Intel Core i3 (2 ядра / 4 потока).

результат

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();
}}}

Изменить : более гольф версия (322 символа), та же функциональность:

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();
}}}

1
Там есть знак «меньше», который интерпретируется как HTML и портит форматирование.
Дэвид Конрад

@ValekHalfHeart следующие две строки должны объяснить это. Executor - это поток (асинхронный диспетчер задач), выполняющий задачи (здесь циклы) до прерывания. После его создания основной поток ждет 1,5 с, а затем прерывает все задачи.
PTwr

45
Просто открыв Eclipse, мой график процессора написал «Простой протокол передачи почты».
lolesque

21

C 78 байтов

Вы никогда не говорили, что мы не можем принять пользовательский ввод, ооочень ..

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

Эта программа читает из стандарта in и каждый раз, когда она читает символ, она выполняет бесполезную трату ЦП на цикл, а затем снова вызывает main. Вы управляете количеством процессорного времени, которое он использует, спамом вводя клавишу на разных скоростях.

Я запускал его на Intel i3 4130T, который является довольно новым процессором. Но ваш пробег может варьироваться, если он использует больше или меньше процессорного времени, чем вам удобно наблюдать, попробуйте поиграть с величиной сдвига в цикле задержки.

Моя программа потрясающая, потому что она:

  • в основном кроссплатформенный, он должен работать с очень малой тряской на любом * nix
  • побеждает вопрос
  • отличная игра в эндшпиле

После нескольких попыток я создал график, который выглядел так:График процессора


Это помогает ограничить его одним ядром процессора с набором задач, a.la. taskset -c 1 [file]
Вуг

2
В требованиях к задаче я не вижу ничего, что говорит о том, что наши материалы будут вызываться какyes | [program]
Wug


1
"отличная игра в эндшпиль" заставила меня усердно повеселиться +1
Кристоф

1
Этот ответ слишком хорош, черт побери, лазейки!
Волшебная Урна Осьминога
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.