1. C++ / Говнокод #23178

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    83. 83
    84. 84
    85. 85
    86. 86
    87. 87
    88. 88
    89. 89
    90. 90
    91. 91
    #include <algorithm>
    #include <exception>
    #include <iostream>
    #include <memory>
    #include <string>
    #include <vector>
    #include <random>
    #include <chrono>
    #define __CL_ENABLE_EXCEPTIONS
    #include "cl.hpp"
    
    using namespace std::string_literals;
    
    
    int main(int argc, char * argv[]) {
      
      
      size_t data_len = (1024 * 1024 * strtoul(argv[1], nullptr, 10)) / sizeof(uint32_t),
             out_len = strtoul(argv[2], nullptr, 10),
             iter = strtoul(argv[3], nullptr, 10),
             block_size = strtoul(argv[4], nullptr, 10);
      
      std::string src = R"(
        typedef unsigned int uint32_t;
    __kernel void bench(global const uint32_t * data, global uint32_t * out) {
        
        uint32_t res = 0, id = get_global_id(0), next = id;
        for(uint32_t i = 0; i < )"s + std::to_string(iter) + R"(; ++i) {
            for(uint32_t j = 0; j < )" + std::to_string(block_size / sizeof(uint32_t)) +  R"(; ++j)
                res ^= data[next + j];
            next = data[next];
        }
        out[id] = res;
        
    }
      
      )"s;
      
      cl::Program::Sources sources = {{src.data(), src.size()}};
    
    
      std::vector<cl::Platform> platforms;
      cl::Platform::get(&platforms);
      
      std::vector<uint32_t> data(data_len);
      std::vector<uint32_t> out(out_len);
      
      std::generate(std::begin(data), std::end(data), [=,gen = std::mt19937{}]() mutable {
        return gen() % (data_len - (block_size / sizeof(uint32_t)));
      });
      
      for(auto & platform : platforms) {
        std::cout << "Using platform: " << platform.getInfo<CL_PLATFORM_NAME>() << "\n";
        std::vector<cl::Device> devices;
        platform.getDevices(CL_DEVICE_TYPE_GPU, &devices);
        for(auto & device : devices) {
          try {
            std::cout << "Using device: " << device.getInfo<CL_DEVICE_NAME>() << "\n";
            cl::Context ctx({device});
            cl::Program program(ctx, sources);
            program.build({device});
            
            cl::Buffer data_buffer(ctx, CL_MEM_READ_WRITE, data.size() * sizeof(uint32_t));
            cl::Buffer out_buffer(ctx, CL_MEM_READ_WRITE, out.size() * sizeof(uint32_t));
            cl::CommandQueue queue(ctx, device);
            queue.enqueueWriteBuffer(data_buffer, CL_TRUE, 0, data.size() * sizeof(uint32_t), data.data());
            
            cl::make_kernel<cl::Buffer &, cl::Buffer &> bench(program, "bench");
            cl::EnqueueArgs eargs(queue,cl::NullRange,cl::NDRange(out.size()),cl::NullRange);
            
            auto start = std::chrono::high_resolution_clock::now();
            bench(eargs, data_buffer, out_buffer).wait();
            auto time = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start).count();
            
            size_t ops = out_len * iter;
            size_t total_tp = ops * block_size;
            double miops = (ops / time) / (1000 * 1000);
            double tpgbps = (total_tp / time) / (1024 * 1024 * 1024);
            fprintf(stderr, "Result: %.2fMIOPS, %.2fGB/s, %.2fsec\n", miops, tpgbps, time);
            
            
            queue.enqueueReadBuffer(out_buffer, CL_TRUE, 0, out.size() * sizeof(uint32_t), out.data());   
          
          } catch(cl::Error e) {
            std::cout << e.what() << " : " << e.err() << std::endl;
            std::terminate();
          }
        }
        
      }
    }

    Код Царя
    https://www.linux.org.ru/forum/development/13489159
    https://github.com/superhackkiller1997/gpu_mem_benchmark/blob/master/main.cpp

    Запостил: j123123, 12 Июля 2017

    Комментарии (41) RSS

    • Можете объяснить, что это вообще за хуита такая?
      .
                               VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
      for(uint32_t i = 0; i < )"s + std::to_string(iter) + R"(; ++i) {
          for(uint32_t j = 0; j < )" + std::to_string(block_size / sizeof(uint32_t)) +  R"(; ++j)
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      Ответить
      • Ты где-то не там стрелки нарисовал, конструкция выше начинается:

        R"(....)"s + std::to_string(iter) + R"(...)"s + ...

        R"(...)" — это raw string literal, см. http://en.cppreference.com/w/cpp/language/string_literal пункт (6)

        Суффикс s — "..."s — это новомодный способ скастить массив символов в строку, который, к слову, тут не нужен
        http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s
        Ответить
        • Остаётся добавить в кресты синтаксис для интерполяции параметров:
          s = "test: ${function(param)}!"; // s = "test: " + function(param) + "!";
          Ответить
        • Б**** какое п********* е***** г**** эти ваши плюсы, поубивал бы
          Ответить
    • Вот кстати, если б например гомоиконность, не нужна была бы ебля со строками типа
      std::string src = R"(
          typedef unsigned int uint32_t;
      __kernel void bench(global const uint32_t * data, global uint32_t * out) {
          
          uint32_t res = 0, id = get_global_id(0), next = id;
          for(uint32_t i = 0; i < )"s + std::to_string(iter) + R"(; ++i) {
              for(uint32_t j = 0; j < )" + std::to_string(block_size / sizeof(uint32_t)) +  R"(; ++j)
                  res ^= data[next + j];
              next = data[next];
          }
          out[id] = res;
          
      }
        
      )"s;

      а достаточно было б ебли с AST
      Ответить
      • Не уверен, что тут и гомоиконность-то особо нужна. Достаточно небольшого DSL для манипуляции AST ядер. На хачкелях такое довольно неплохо выглядит без всякой гомоиконности https://hackage.haskell.org/package/accelerate.
        В плюсах тоже можно что-то подобное запилить, если как следует обмазаться boost::proto.
        Halide тоже без гомоикон обошёлся http://halide-lang.org/
        Ответить
        • boost::proto является приделанным сверху костылем через плюсоуебанские шаблоны и прочее говно, то ли дело лисп

          А про хаскель сказать ничего не могу, но гомоиконности там нет, это точно. И темплейт хаскел это не гомоиконность
          Ответить
          • > но гомоиконности там нет, это точно

            Но она там и не нужна. Программирование с монадами в хаскеле по сути выглядит как конструирование структуры данных, которая потом интерпретируется специальной функцией (runReader, runWriter, runState, etc.). Разные монады — разные семантики выполнения кода. Монадический сахар делает структуры данных более похожими на код, но по сути мы оперируем кодом как структурой данных, только вместо унылых гетерогенных списков у нас удобные типизированные конструкторы данных и паттерн-матчинг с анализатором кейсов.
            Монадические стеки — это по сути конвееры: "программа" X конструирует "программу Y", которая конструирует "программу IO". Интерпретатор монад ST и IO (частный случай ST) вшиты в рантайм, поэтому они всегда должны быть последними в стеке.
            Ответить
            • Вут? Так в хачкиле императивщина отдельно встроена прямо в язык? Мдаа.
              Ответить
              • > Так в хачкиле императивщина отдельно встроена прямо в язык?

                Не понятно, что ты имеешь в виду. Весь ввод-вывод имеет тип IO t, что означает "действие, результатом выполнения которого будет значение типа t". Так чистые функции можно отличить от функций "с побочными эффектами" на уровне типов.
                Ответить
                • Да я и сам не понял, что имею в виду. Меня просто удивило, что хаскель полагается на какой-то сторонний интерпретатор императивных программ для того, чтобы делать всякое и/о.
                  Ответить
                  • Какой же он сторонний, если он вшит в рантайм, а семантика описана в стандарте? Тебя не удивляет, что язык C полагается на какую-то стороннюю реализацию printf?
                    Ответить
                    • Ну она на си написана, с поправкой на всякие сисколы.
                      Ответить
                    • Я на Си могу под контроллеры без всяких printf спокойно писать
                      Ответить
                      • Так ты и без всяких гомоикон можешь спокойно под контроллеры песать.
                        Ответить
                        • Сделаю гомоиконы в Forth и буду писать под контроллеры на Forth с гомоиконами
                          Ответить
                          • Пиздуй в очко, семя каинское.
                            Ответить
                          • Но зачем они там? В Factor, Joy и других фортах есть [ цитирование ] , которое их успешно заменяет (кстати, фортовское цитирование -- крайне няшная альтернатива каррированию).
                            edit: Ответ на коммент выше.
                            Ответить
                            • Нужно сделать на самом языке систему символьных вычислений (ССС) над его же кодом/AST и используя эту ССС иметь возможность например выводить определенные свойства реализации (формальная верификация, как например с использованием Frama-C с применением SMT-решателей, Coq, Agda), использовать эту ССС для целей вроде суперкомпиляции/супероптимизации. Или чтобы циклы например анроллить, типа вот мы задаем каким-то там макаром, что вот тут у нас цикл, и говорим нашей ССС что вот наанроль его вот таким образом, и потом будет там наанроленный цикл. Или реализовывать свои domain-specific оптимизации для каких-нибудь бигинтов. Или эту же ССС можно попросить, чтобы например она трансформировала код некой функции таким образом, чтобы она вместо int принимала long long int, чтобы это было еще в IDE интегрировано нормально, и чтобы такую кодогенерацию при желании даже в рантайме можно было бы делать, если с собой в рантайм тащить еще JIT с VM (т.е. тащить какую-то жирную хрень типа JVM) и AST, удобный для трансформации. Можно сделать что-то вроде тех же Java оптимизаций в рантайме, рантайм-профилирование и трансформация кода в процессе. Или даже profile-guided optimisation (PGO) потом сделать на основе собранной статистики, т.е. вот типа набрали мы статистики при выполнении кода в VM и потом использовали ее чтобы полностью четко скомпилировать в бинарник, чтоб без VM все выполнялось. Вот это я понимаю круто будет.
                              А остальное говно и сосет
                              Ответить
                              • Сначала думал, что вореции

                                Этому, конечно, далеко до того, что ты написал, но выглядит оно интересно http://mbeddr.com/
                                Ответить
                              • Впервые ты что-то дельное сказал.
                                Ответить
              • Нет, но на Haskell императившину можно идиоматично описать, если отказаться от ссылочной прозрачности путём скрытия данных вглубь модулей.
                И такая "эмулированная" императивщина настолько настоящая, что компилятор оптимизирует её до настоящей императивщины ^___~
                Ответить
                • Только GC в вашем хачкеле на иммутабельную функциональную парашу заточен, а не на императивщину
                  Да и сам по себе GC это та еще параша. Надо бы гомоиконы без GC придумать
                  Ответить
            • А че такое уникальные типы?
              Ответить
            • > Программирование с монадами в хаскеле по сути выглядит как конструирование структуры данных, которая потом интерпретируется специальной функцией (runReader, runWriter, runState, etc.).

              И насколько это гибко? Можно ли (и если да, насколько сложно (страшно) это будет выглядеть) сделать на этих монадах meta-circular evaluator, т.е. реализацию интерпретатора в интерпретаторе, посредством которого бы можно было легко расширить исходный язык?
              Ответить
        • Хм, accelerate ещё жив, вот не ожидал.
          Ответить
        • https://www.quora.com/Why-is-Haskell-not-homoiconic вот что ML-ёбы про гомоиконы говорят

          >The main reason Haskell isn’t homoiconic is that Haskell is a modern programming language that was born long after most programming language developers realised that homoiconicity is a terrible idea. Indeed, homoiconicity died with early Lisp. Even recent direct descendants like Clojure diverge from this idea by adding syntax for indexing and vectors.

          >I see that other answers have conflated homoiconicity with metaprogramming. They are not related. We have better forms of metaprogramming now. The Meta Language (ML) family of programming languages were specifically bred for metaprogramming and Haskell is derived from them. Concepts like algebraic data types and ML-style pattern matching are a far more powerful tool for metaprogramming than anything Lisp ever got.

          И это программисты?
          Ответить
          • > ML
            > И это программисты?
            Очевидно нет. Борщехлебы, такие же как и лишперы.
            Ответить
      • > ебли с AST
        Недавно читал статейку Саттера про рефлексию, метаклассы и компайл-тайм генерецию кода. Скоро завезут эту самую ёблю, походу.
        Ответить

    Добавить комментарий