#6 hlucheucho
Zadání nevypadá, že by mělo jít o čísla v mezinárodním formátu. I tak na ně stačí 40 bitů tj. 32+8 ;-).
Příspěvky odeslané z IP adresy 89.177.163.–
Naklonoval jsem do Visual Studia 2017 projekt z GitHubu, ale nikde nevidím *.sln Při pokusu vše znovu sestavit dostanu chybu:
Manually-specified variables were not used by the project: CMAKE_CXX_COMPILER
Jak vyzkoušet příklady na stránce GPU Computing on OpenCL ve Visual Studiu 2017 v C++ ? Podporu pro CUDA mám naistalovanou.
Předpokládám, že ukázka potřebuje na začátku definovat nějakou hlavičku:
//CPU (Intel i7-5960X)
int sum()
{
int sum = 0;
const int* set = _gen_randoms;
int i = 0;
for(i = 0; i < N; ++i) {
sum += set[i];
}
return sum;
}
Představu mám zcela jasnou. Program by měl pomocí umělé inteligence analyzovat graf EKG. Výstupem by mělo být buď že je graf v pořádku, nebo podezření na nějaké poškození srdce.
Viz např. projekt Welcome to BrainFlow’s documentation! na Githubu. Projekt počítá s konkrétními HW snímači signálů, které pořizují záznam dat. Nemělo by být ale tak složité, převést data získaná jinak na vhodný formát a nechat je pak zpracovat programem.
#11 Kit
AI pracuje s grafikou ;-). Na data by to šlo převést pomocí digitalizace grafu např. https://www.stahuj.cz/grafika_a_design/ostatni/engauge-digitizer/
PDF graf je po měření generován Android aplikací, data na mobilu někde jsou, ale nemohu najít instalační adresář. Pracuji na tom ;-).
#9 Kit
Data jsou v pdf viz odkaz ke stažení zde https://ufile.io/e7f8tunf (použij slow download).
Myslím, že v daném případě nejde o zpracování signálu ale obrazu viz např. článek "Multi-class Arrhythmia detection from 12-lead varied-length ECG using Attention-based Time-Incremental Convolutional Neural Network" https://www.sciencedirect.com/science/article/pii/S1566253518307632
Já bych se toho nebál. Znalost mikrokontrolerů má určitě využití v průmyslu i jinde. I když nejsem nejmladší, přes měsícem jsem si pořídil Arduino Pro Mini ATMega328P 3.3V a modem Wisol (Sigfox) a rozchodil vlastní program na měření napětí autobaterie každou hodinu. Nyní jsem přešel na vyšší level a koupil si ATtiny202 (trochu mě vyděsila jeho "velikost" cca 4x4 mm a osm nožiček ????), debugger MPLAB SNAP a nahrál MPLAB X IDE vývojové prostředí. Určitě "nacpu" program z Arduina (8 kB) do ATtiny202 (max. 2 kB).
Na notebooku jsem si v C++ a x64 assembleru I7 udělal program, který načte TXT soubor o velikosti 4 GB nejednou do paměti a pak s ním pracuji. TXT soubor má 38 milionů řádků, které obsahují GPS souřadnice NOAA bójí. Neměl jsem problém data (převedené na int) v assembleru pomocí merge sort setřídit, indexovat a vyhledat hodnoty binárním hledáním včetně vynesení výsledku na mapu světu. Program během cca 3 sekund zpětně vyhledá nejpravděpodobnější místo, odkud se dostalo 12 nalezených trosek letu MH370, ve čtvercové síti souřadnic od 0° do 40°S a 80° až 108°E. Výsledkem je 4°-5°S a 80°-81°E.
Doporučuji zkusit navázat spolupráci formou brigády s nějakou firmou, která mikrokontrolery používá.
Abych jen neradil, stáhni si Visual Studio 2019 Community:
Compiling 64-bit Assembler Code in Visual Studio 2013
Introduction to x64 Assembly
Ve vlastnostech konfigurace projektu "Intel Performance Libraries" mám ve Visual Studiu 2017 nastaveno "Use Intel TBB" = Ne.
V Linker, Obecné mám v "Další adresáře knihoven" nastavenu cestu C:\Program Files (x86)\IntelSWTools\parallel_studio_xe_2019.0.045\compilers_and_libraries_2019\windows\tbb\lib\intel64\vc14
která obsahuje knihovny tbb.dll a tbb_debug.dll
Program se zkompiluje (konfigurace debug) v pohodě, ale při pokus o jeho spuštění (F5) dostanu hlášky:
Kód nejde spustit, protože se nenašel tbb.dll a tbb_debug.dll. Pokuste se tento problém vyřešit přeinstalací programu.
Při "Use Intel TBB" = Ano se chybové hlášky nezobrazí, program se spustí ale hned ukončí, u funkce fopen skončí s chybou, že nemůže načíst textový soubor
Jde o vzorový program YOLO v2 (darknet) s CUDA. Když jsem OpenCV dříve zkompiloval jen s CUDA a MKL bez TBB, tak šlapal jako hodinky.
V čem je problém ?
#4 MilanL
Chtěl bych zkusit hledání velkých prvočísel. Našel jsem ale tip, jak na to celkem jednoduše. Vydám se asi cestou svých zkušeností s alokací několika GB paměti a x64 assembleru. Nebude to legrace pracovat s čísly, která mají více než 24 milionů číslic. P.S. Poslední nalezené provočíslo se vejde do 10 323 742 bytů.
Viz článek zde
Chtěl bych vykoušet ukázkový příklad CUDA accelerated(X) Multi-Precision library viz odkaz zde
Na řádcích za //import a //export ale dostávám chybové hlášení:
Argument typu "uint32_t *" je nekompatibilní s parametrem typu "uint32_t"
Co s tím ?
#include "xmp.h"
#include <stdio.h>
#include <stdlib.h>
#include <C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\include\cuda_runtime_api.h>
#define XMP_CHECK_ERROR(fun) \
{ \
xmpError_t error=fun; \
if(error!=xmpErrorSuccess){ \
if(error==xmpErrorCuda) \
printf("CUDA Error %s, %s:%d\n",cudaGetErrorString(cudaGetLastError()),__FILE__,__LINE__); \
else \
printf("XMP Error %s, %s:%d\n",xmpGetErrorString(error),__FILE__,__LINE__); \
exit(EXIT_FAILURE); \
} \
}
int main() {
int i, w;
int N = 10000;
int bits = 1024;
xmpIntegers_t base, mod, exp, out;
uint32_t *b, *m, *e, *o;
uint32_t limbs = bits / 8 / sizeof(uint32_t);
size_t bytes = N * bits / 8;
b = (uint32_t*)malloc(bytes);
o = (uint32_t*)malloc(bytes);
m = (uint32_t*)malloc(bits / 8);
e = (uint32_t*)malloc(bits / 8);
xmpHandle_t handle;
//allocate handle
XMP_CHECK_ERROR(xmpHandleCreate(&handle));
//allocate integers
XMP_CHECK_ERROR(xmpIntegersCreate(handle, &base, bits, N));
XMP_CHECK_ERROR(xmpIntegersCreate(handle, &out, bits, N));
XMP_CHECK_ERROR(xmpIntegersCreate(handle, &exp, bits, 1));
XMP_CHECK_ERROR(xmpIntegersCreate(handle, &mod, bits, 1));
//initialize base, exp, and mod
for (i = 0; i < N; i++) {
for (w = 0; w < limbs; w++) {
b[i*limbs + w] = rand();
}
}
for (w = 0; w < limbs; w++) {
m[w] = rand();
e[w] = rand();
}
//make sure modulus is odd
m[0] |= 1;
//import
XMP_CHECK_ERROR(xmpIntegersImport(handle, base, N, limbs, -1, sizeof(uint32_t), 0, 0, b));
XMP_CHECK_ERROR(xmpIntegersImport(handle, exp, 1, limbs, -1, sizeof(uint32_t), 0, 0, e));
XMP_CHECK_ERROR(xmpIntegersImport(handle, mod, 1, limbs, -1, sizeof(uint32_t), 0, 0, m));
//call powm
XMP_CHECK_ERROR(xmpIntegersPowm(handle, out, base, exp, mod, N));
//export
XMP_CHECK_ERROR(xmpIntegersExport(handle, o, N, &limbs, -1, sizeof(uint32_t), 0, 0, out));
//use results here
//free integers
XMP_CHECK_ERROR(xmpIntegersDestroy(handle, base));
XMP_CHECK_ERROR(xmpIntegersDestroy(handle, out));
XMP_CHECK_ERROR(xmpIntegersDestroy(handle, exp));
XMP_CHECK_ERROR(xmpIntegersDestroy(handle, mod));
//free handle
XMP_CHECK_ERROR(xmpHandleDestroy(handle));
free(b);
free(o);
free(m);
free(e);
printf("done\n");
return 0;
}
V modulu cuda.h mi to hlásí varování na řádku:
dim3 cuda_gridsize(size_t n);
warning C4190: cuda_gridsize má zadanou funkci C-linkage, ale vrací UDT dim3 nekompatibilní s jazykem C
Ve vectors_types.h je definováno:
struct __device_builtin__ dim3
{
unsigned int x, y, z;
#if defined(__cplusplus)
__host__ __device__ dim3(unsigned int vx = 1, unsigned int vy = 1, unsigned int vz = 1) : x(vx), y(vy), z(vz) {}
__host__ __device__ dim3(uint3 v) : x(v.x), y(v.y), z(v.z) {}
__host__ __device__ operator uint3(void) { uint3 t; t.x = x; t.y = y; t.z = z; return t; }
#endif /* __cplusplus */
};
typedef __device_builtin__ struct dim3 dim3;
V čem je problém ?
Na svém notebooku s W10, OpenCV 3.4.0, CUDA & CDNN a Visual Studio 2017 jsem si stáhl repozitář projektu YOLO v2 a úspěšně ho zkompiloval. Vše funguje jak má vč. rozpoznání objektů v demo videu:
darknet.exe detector demo data/voc.data yolo-voc.cfg yolo-voc.weights test.mp4 -i 0
Nechápu, proč se mi nedaří použí místo videa signál webcamery z notebooku:
darknet.exe detector demo data/voc.data yolo-voc.cfg yolo-voc.weights
U web kamery se na zlomek sekundy rozsvítí LEDka, že kamera naběhla, ale program vzápětí skončí s hláškou "Stream closed.: No error". Hláška je vidět v části demo.c viz níže
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/core/version.hpp"
#ifndef CV_VERSION_EPOCH
#include "opencv2/videoio/videoio_c.h"
#endif
image get_image_from_stream(CvCapture *cap);
static char **demo_names;
static image **demo_alphabet;
static int demo_classes;
static float **probs;
static box *boxes;
static network net;
static image in ;
static image in_s ;
static image det ;
static image det_s;
static image disp = {0};
static CvCapture * cap;
static float fps = 0;
static float demo_thresh = 0;
static float *predictions[FRAMES];
static int demo_index = 0;
static image images[FRAMES];
static IplImage* ipl_images[FRAMES];
static float *avg;
void draw_detections_cv(IplImage* show_img, int num, float thresh, box *boxes, float **probs, char **names, image **alphabet, int classes);
image get_image_from_stream_resize(CvCapture *cap, int w, int h, IplImage** in_img);
IplImage* in_img;
IplImage* det_img;
IplImage* show_img;
void *fetch_in_thread(void *ptr)
{
//in = get_image_from_stream(cap);
in = get_image_from_stream_resize(cap, net.w, net.h, &in_img);
if(!in.data){
error("Stream closed.");
}
//in_s = resize_image(in, net.w, net.h);
in_s = make_image(in.w, in.h, in.c);
memcpy(in_s.data, in.data, in.h*in.w*in.c*sizeof(float));
return 0;
}
Web kamera přitom v jiném projektu s krátkým kódem funguje v pohodě:
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
namedWindow("edges", 1);
for (;;)
{
Mat frame;
cap >> frame; // get a new frame from camera
cvtColor(frame, edges, CV_BGR2GRAY);
GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);
Canny(edges, edges, 0, 30, 3);
imshow("edges", edges);
if (waitKey(30) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
Netušíte někdo, v čem může být problém ?
Nemá někdo tip, jak na to ? Jde mi o naprogramování systému, který by pomocí dotazů na příznaky nemoci byl schopen určit možnou nemoc/i. Ideálně by měl na základě odpovědí také umět poradit jaká další vyšetření provést.
Jako odrazový můstek jsem našel
https://www.geeksforgeeks.org/…ntroduction/
#74 MilanL
Díky, díval jsem se na to, ale bohužel tam není nějaká praktická ukázka.
Pro představu nyní trvá mému programu 7 minut, než spočítá součin počtu bójí pro 9 míst s nalezenými troskami (+/- 0,5°) a cyklem, který projíždí oblast Indického oceánu po 1°x1° od 0° až 40° S a 80° až 108° E. Pro každou z 9 oblastí to představuje 41*29 čtverců = 1 189. V každém čtverci se z 20 000 bójí, které obsahují 35 mil. GPS souřadnic, hledá počet bójí, které se pohybovaly v místě nálezu jedné z devíti trosek a aktuálním čtvercem 1°x1°. Výsledkem je heat mapa 41*29, kde je v každém čtverci součin nalezených bójí (výchozí hodnotu jsem samozřejmě nastavil na 1). Nejvyšší hodnota 4 599 504 je ve čtverci 24 S 81 E (na jedno z devít míst nálezů tak v půměru doplulo 4 599 504 ^ (1/9) = 5,50 bójí) pak udává místo, které lze s nejvyšší pravděpodobností považovat za místo, odkud začalo svou dráhu všech devět trosek do míst svých nálezů.
#72 Jerry
Předpokládám, že se v tom DirextX12 vyznáš. Rady typu ať si to nastuduji od začátku jsou mi na nic. Takhle bych si nedovolil někomu "radit". Pokud sem neuvedeš krátké příklady, jak předat data do paměti, najít bóje pomocí dvou zadaných oblastí a jak je vykreslit, tak je hotovo. Pokud víš jak na to, tak to přece nemůže být žádná věda. Fakt to nebudu zkoumat, když dopředu nevím, zda DirectX12 potřebné funkce vůbec má. Odkaz na ukázku "How to use DrawLine in C++ (DirectX Graphics)" je o ničem...
#69 Jerry
Není mi jasný, jak mi DirectX2D zrychlí vykreslení trasy po úsečkách, když nyní používám jeden příkaz na vykreslení celé trasy (5 000 "úseček") pomocí GDI Polyline ?
Jak píšeš o tom zdrojáku, tak nemám problém s jakoukoliv velikostí, musí jít ale přeložit pomocí Visual Studio 2017. Nechápu proč má 60 000 řádků. Se zoomováním ve svém programu pomocí myši počítám taky, ale vidím to na max. 50 řádků :-).
Nepotřebuji použít nějaký hotový program, musím ale jasně vědět, jak danou funkci použít ideálně na příkladu. Nebráním se zkusit pro vyhledání bójí použít funkce grafické karty, ale vůbec netuším, jak jí předat údaje o 20 000 bójích a 35 mil. GPS souřadnic.
Pokud se v tom vyznáš, tak mi prosím napiš, jak mám data načíst do paměti grafické karty, najít podle dvou oblastí bóje, jejichž trasy prošla alespoň jednou oběma oblastmi a jak nalezené trasy bójí zobrazit.
#66 Jerry
Díky za snahu, ale v C++ jsem v podstatě začátečník. Na takové rozsáhlé projekty nemám. Pokud mi sem někdo nedá kód, jak ty bóje z dat najít (pomocí funkcí grafické karty) a vykreslit pomocí DirectX12, tak je hotovo.
Nemám problém vykreslit trasy pomocí GDI Polyline viz můj výsledek C++ a x64 assembler ;-)
#61 Jerry
Díky, stáhl jsem, změnil odkaz na nejnovější SDK a a zkusil přeložit. Chybí tam Segment_1h:
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
#pragma once// TODO: reference additional headers your program requires here
#include "c:\ROBOMAP Source Code\_common libs\Segment_1.h"
#include "Stepping.h"
#include "ProcessManagement.h"
#include "EstimatorProperties.h"
#include "StartPoseA.h"
#include "MapViewer2D.h"
#include "MapViewer_Settings.h"
#include "PenDialog.h"
#include "LSBViewer.h"
#include "RSResultsA.h"
#include "ContinualLocalizationjDE.h"
#include "Form1.h"
#include "ClassReg.h"
#54 Jerry
S grafickou karotu nemám absolutně žádnou zkušenost. Pokud jsem dáš zdroják, jak na to, vyzkouším to.
Vyhledání bójí si lze vyzkoušet, odkaz na setříděný soubor podle Data, ID, LAT, LON jsem zde uvedl o několik příspěvků výše a zkusit najít bóje, které např. prošly oblastmi:
//Reunion +-1,5
Laa1 = -19.416;
Laa2 = -22.416;
Loa1 = 54.149;
Loa2 = 57.149;
a
// Druhá oblast
lab1 = -11.0;
lab2 = -12.0;
lob1 = 84.0;
lob2 = 85.0;
#45 Jerry
Se zobrazením není problém. Např. 7 tras bojí z nichž každá obsahuje v průměru 1 500 souřadnic se pomocí funkce
Polyline(hdc, apt, bodu);
vykreslí v C++ ihned. Časový problém byl ty bóje rychle najít a zvlášť opakovaně, když jsem ve dvou smyčkách projížděl celý Indický oceán po 1°x1°.
#47 MilanL
To, že ve čtverci 1°x1° hledám bóje, které jím prošly vůbec nesouvisí s nějakým "hrubým rozlišením". Jde prostě jen o to prohledal trasy bojí a vybrat z nich ty, které prošly daným čtvercem. Ve finále jsem pro 6 trosek našel ve čtverci 11° S 84° E nejvyšší součin (abych zřetelně viděl oblasti, kterými prošlo nejvíce bójí) počtu bójí = 1 600 (vyšší hodnotu u rovníku jsem nebral v úvahu, protože tímto čtvercem neprošly bóje ze všech šesti oblastí, kde se pak trosky našly – jejich souřadnice zde pak pro hledače napíšu). Danou oblastí prošlo 8 bójí, které pak doputovaly do blízkosti místa, kde se na ostrově Reunion našel flaperon, 5 bójí - kryt klapky, 2 bóje – vertikální kormidlo, 2 bóje – kryt motoru, 5 bójí – klapka křídla a 2 bóje – Mossel Bay.
Oceňuji vaši pomoc, více hlav více ví.
P.S. Převedená data včetně indexů máš v tom SRT souboru.
Výsledná "heat map" pro 6 oblastí, kde se našly trosky:
https://image.ibb.co/bZnQup/HMH370_Heat_Map.jpg
#40 Jerry
Ano, postupuji přesně tak, jak jsi to popsal.
Amatérsky za zajímám o letecké katastrofy včetně záhady zmizení MH370. Mj. jsem v kontaktu s očitým svědkem pozorování hořícího "objektu" Mikem McKayem z Nového Zélandu. Po zadání souřadnic 6 nalezených trosek (vč. flaperonu na ostrově Reunion) a procházením Indického oceánu ve dvou vnořených cyklech po 1° od 0° do 40° S a od 80° do 108° E jsem pomocí programu zjistil jako nejpravděpodobnější místo původu nalezených trosek souřadnice 11° S a 84° E (v tomto čtverci jsem v součinu našel nejvíce bóji, kterou danou oblastí propluly a dostaly se do blízkosti míst nálezů všech trosek). V cyklu 2x 35 mil. řádků trval výpočet jedné oblasti 1°x1° cca 2,5 sekundy. Půlením intervalu (25 porovnání) to bude určitě ihned. Jde o oblast rovníkových proudů, do které se podle mého názoru mohly trosky snadno dostat z pobřeží Vietnamu přes Sundskou úžinu mezi Sumatrou a Jávou. Let MH370 podle mě a podle všech dostupných informací havaroval v Jihočínském moři u pobřeží Vietnamu.
Dnes snad dokončím upravený program, který hledá data pomocí půlením intervalu, to již spolehlivě funguje. Nalezené bóje musím jen zkopírovat za sebe pro jejich předání C++, aby je vykreslil na mapě.
Někdo my také radil použít např. QGIS, grafický informační systém. Ten ale není stavěn na miliony řádků. I když jsem data převedl do tvaru jeho databáze, trvá pouhé otevření dat asi 10 minut… Dříve jsem používal Excel, kdy jsem textový soubor externě připojil pomocí PowerQuery v Excelu a zadáním podmínek hledání jsem dostal souřadnice do tabulky v Excelu. Jeden dotaz trval cca 3 minuty. Pak jsem souřadnice nalezených bójí převedl na jedné webové stránce z Excelu do KML a vynesl na Google Earth.
Přidávám ještě odkaz na převedená (DWORD) a setříděná data, popis pozic viz výše, v souboru je 22 797 bójí a má 35 702 067 řádků:
https://uloz.to/!XpZdcLPdtNC7/srt-180823-dat
A příklad výstupu mého programu (hledání), vynesení bójí ještě přes Excel a Google Earth:
https://image.ibb.co/f2mck9/MH370_6_1184.jpg
#37 MilanL
Data jsem stáhl ze stránky http://www.aoml.noaa.gov/phod/gdp/index.php. Ty čtyři soubory *dat.gz jsem sloučil do jednoho a nahradil desetinné tečky čárkou. Na stránce ftp://ftp.aoml.noaa.gov/phod/pub/buoydata/ je jejich popis včetně struktury, soubor "header_buoydata.txt".
Když budeš potřebovat, mohu ti poslat odkaz na setříděný soubor podle LAT, LON, ID a data/času. Soubor je stejný, jako ten co máš, jen jsem na nevyužitá místo v řádku uložil DWORD hodnoty LAT, LON... a DWORD odkaz na řádek kde lze pomocí nepřímého odkazu přečíst setříděnou hodnotu. Příklad: na prvním (nultém) řádku setříděného souboru najdeš na pozicích 56 DWORD LAT (hodnota ASCII ze začátku řádku) a hned za ní, pozice 60 DWORD odkaz na řádek, kde je nejnižší hodnota LAT, vynásobením tohoto čísla 125 dostaneš č. řádku s nejnižší hodnotou LAT na pozici 56 DWORD. Odkaz na další stejnou nebo vyšší hodnotu LAT je pak na dalším řádku atd. Dtto pro LON (64 + index 68), ID (72 + 76) a Datum/čas (80 + 84). Datum čas jsem převedl do DWORD na počet bitů 11+4+5+2 t.j. rok, měsíc, den a 1/4 dne. Tj. 7.9.2018 + 3*6 hodin je ve tvaru 0x3F149F.
#32 MilanL
Když si stáhneš Visual Studio 2017 tak můžeš dělat i v 64 bitech. Jak na to zde https://deviorel.wordpress.com/2015/01/19/compiling-64-bit-assembler-code-in-visual-studio-2014/
Nesetříděný textový soubor s daty 4 GB je ke stažení na https://uloz.to/!mQDfiGbQdDlP/bda-180823-dat
Pevné pozice, šířka sloupců: 8, 5, 7, 5, 10, 10, 80. Počet řádků 35 702 066.
č. bóje (ID), měsíc, den a 1/4 dne (GPS pozice odesílány každých 6 hodin), rok, LAT, LON, nepotřebná data
Pro začátek lze najít 7 bójí (čísla znám), které prošly oblastí:
LATa1 = -5,9;
LATa2 = -6,6;
LONa1 = 104,8;
LONa2 = 106,6
Mohu také případně nahrát soubor s ASCII údaji převedenými na DWORD + DWORD s nepřímým odkazem na setříděné hodnoty LAT, LON a ID. Ponechal jsem v něm ale také původní ASCII hodnoty.
#20 MilanL
Program hledá čísla bójí, které se pohybovaly ve dvou čtvercových oblastech podle zadaných LAT/LON. Nevadí, že nějaká bóje oblast opustí a pak se do ní vrátí. Ve finále pak vynáším celou trasu bojí, které jsem našel (t.j. trasa dané bóje prošla oblastí 1 a 2). Při kreslení musím ještě přepočítat souřadnice na body na obrazovce a uložit trasu do pomocného vektoru pro funkci Polyline(hdc, *apt, cpt), to už dělám v C++.
Na třídění (soubor si pak uložím a nemusím data pokaždé třídit) používám Merge Sort. Celočíselné násobení 125 je velmi rychlé, vynásobení rcx 125 za pomoci násobků 2, posunů a sčítání je pomalejší:
mov rax, rcx
shl rcx, 2 ; *4
add rax, rcx
shl rcx, 1 ; *8
add rax, rcx
shl rcx, 1 ; *16
add rax, rcx
shl rcx, 1 ; *32
add rax, rcx
shl rcx, 1 ; *64
add rax, rcx
#17 MilanL
Takhle nějak to dělám ;-). Originální data jsou v textovém souboru s pevnou délkou sloupců. Souřadnice ve tvaru XXX,xxx převedu na DWORD vynásobením 1 000 a u záporné LAT přičtu 90 000 abych neřešil int se znaménkem, LON hodnoty jsou v rozsahu 0-360°. Za DWORD hodnotami LAT/LON mám pak další DWORD které nepřímo odkazují na řádek s hodnotou LAT/LON po setřídění. Řádek je dlouhý 125 bytů, na začátku ponechám v ASCII č. bóje a LAT/LON, tyto hodnoty mám pak uloženy v DWORD od pozice 56 (kde jsou v ASCI další údaje, které nepotřebuji). Hledám tedy v setříděné tabulce. Vlastní funkce pro hledání půlením intervalu pak reálně vypadá takto:
Najdi: ; r11=L, r12=P, r13=S, r14=pro porovnání, r15=hodnota,rcx=125, rbx=pozice; použit rax a rdx
mov r14, rax ; Hodnota pro porovnání
xor r11, r11 ; L (příprava)
mov r12, 35702066 ; řádků
dec r12 ; pravý okraj pole menší o jedničku
mov rcx, 125 ; Konstanta pro násobení
Najdi_W:
mov rax, r11
cmp rax, r12 ; L <= P ?
ja Najdi_E ; Ne, tj. konec
add rax, r12
shr rax, 1
mov r13, rax ; r13=L+P/2
imul ecx ; edx:eax = eax * ecx
shl rdx, 32
or rax, rdx ; sloučíme Hi edx a Lo eax
add rax, rbx ; Přičteme pozici
mov edx, [rsi+rax+4] ; Vyvedneme č. řádku s odkazem na IND hodnotu LAT/LON
mov eax, edx
imul ecx ; edx:eax = eax * ecx
shl rdx, 32
or rax, rdx ; sloučíme Hi edx a Lo eax
add rax, rbx ; Přičteme pozici
mov edx, [rsi+rax] ; IND hodnota LAT/LON
cmp edx, r14d ; [stred] <= hodnota ?
ja Najdi_D
mov r15d, edx ; Nalezená hodnota
Najdi_D:
cmp r14d, edx ; hodnota > [stred]
ja Najdi_P ; Ano
mov r12, r13
dec r12
jmp Najdi_W
Najdi_P:
mov r11, r13
inc r11
jmp Najdi_W
Najdi_E:
mov rax, r13
inc rax
call Get_IND_Value
cmp edx, r15d ; Hodnota řádek + 1 je stejná ?
ja Najdi_K ; Ne
inc r13 ; Ano, řádek = řádek + 1
jmp Najdi_E
Najdi_K:
ret
Pro ošetření výskytu více stejných hodnat za sebou a nastavení indexu na poslední z nich zprava stačilo na konec programu půlení v assembleru přidat:
mov rax, r13 ; V r13 nalezený řádek (index) zleva
inc rax
call Get_IND_Value ; Vrátí hodnotu na řádku do r15d
cmp edx, r15d ; Hodnota řádek + 1 je stejná ?
ja Najdi_K ; Ne
inc r13 ; Ano, řádek = řádek + 1
jmp Najdi_E
Najdi_K:
#14 MilanL
Dostal jsem tip, jak to správně udělat:
#include <iostream>
#include <algorithm>
int main() {
int arr[] = {0, 2, 3, 5, 5, 6, 8, 8, 8, 9};
auto beg = std::begin(arr);
auto it = std::upper_bound( beg, std::end(arr), 8 );
if( it == beg ) {
std::cout << "no value less than 8 found" << std::endl;
return 0;
}
std::cout << "index is " << std::distance( beg, it ) - 1 << std::endl;
return 0;
}
Funguje to. Rád bych to naprogramoval v assembleru, kde nemohu použít speciální direktivy jako "upper_bound". Viz popis https://en.cppreference.com/w/cpp/algorithm/upper_bound
#10 Jerry
Na to, že se programováním vůbec neživím mi nepřipadá nějaký extrém se naučit základy C++ za cca 3 měsíce pro relativně náročný úkol. Program dělá to co potřebuji, jen se ho teď snažím urychlit. Oceňuji, že mi pomohly i některé rady zde ve fóru :-).
U GPS mi stačí x, y. Sférické souřadnice nepotřebuji.
#7 Jerry
Není mi jasné, k čemu bych měl Fibonacciho čísla použít. Pracuji s GPS souřadnicemi. Hledání čísel půlením intervalu je v sestříděném vektoru o 35 mil. čísel otázkou max. 25x porovnání (log 35 mil. / log 2). Dosud jsem (nesetříděná) čísla hledat ve dvou vnořených cyklech, které jsem procházel 2x 35 milionkrát. I tak to bylo v assembleru prakticky na stisk tlačítka. Půlením intervalu to nyní bude ihned. Potřebuji to pro real time vynášení tras pohybu bójí v moři volbou oblasti pohybem myši na obrazovce.
#3 gna
Takováto rada mi moc nepomůže. Už mi to ale funguje (najde index první hodnoty z více stejných hodnot zleva).
#include "pch.h"
#include <iostream>
int seznam[10]{0, 2, 3, 5, 5, 6, 8, 8, 8, 9};
int arr_size = sizeof(seznam) / sizeof(seznam[0]);
int main()
{
for (int i = 0; i <= arr_size; i++)
{
printf("%i\n", seznam[i]);
}
printf("\n");
int vlevo = 0;
int vpravo = arr_size - 1;
int stred = 0;
int hodnota = 8 ;
bool nasel = false;
int x = 0;
int pozice = 0;
//* Hledámě hodnotu v setříděném poli
while (vlevo <= vpravo) {
stred = (vlevo + vpravo) / 2;
if (seznam[stred] <= hodnota) {
x = seznam[stred];
pozice = stred;
}
if (hodnota > seznam[stred]) {
vlevo = stred + 1;
}
else {
vpravo = stred - 1;
}
}
printf("Nasel jsem %i na pozici %i\n", x, pozice);
}
Jak upravit následující program, aby mi vrátil hodnotu indexu pole po zadání hodnoty = 7, která není v seznamu ? Jde mi vrácení nejvyšší hodnoty indexu pro zadanou hodnotu, kde je hodnota daného čísla v seznamu <= zadané hodnotě. Tj. pro hodnotu = 7 by měl program vrátit index 5 a pro hodnotu = 8 index 8. Data v seznamu jsou setříděna.
#include "pch.h"
#include <iostream>
int seznam[10]{0, 2, 3, 5, 5, 6, 8, 8, 8, 9};
int arr_size = sizeof(seznam) / sizeof(seznam[0]);
int main()
{
for (int i = 0; i <= arr_size; i++)
{
printf("%i\n", seznam[i]);
}
printf("\n");
int vlevo = 0;
int vpravo = arr_size - 1;
int stred = 0;
int hodnota = 3 ;
bool nasel = false;
//* Hledámě hodnotu v setříděném poli
while (vlevo <= vpravo) {
stred = (vpravo + vlevo) / 2;
if (seznam[stred] == hodnota) {
nasel = true;
printf("%i\n", stred);
}
if (hodnota < seznam[stred]) {
vpravo = stred - 1;
}
else {
vlevo = stred + 1;
}
}
}
Už jsem na to přišel. Problém byl v uniform_INT_distribution... ;-) Generátor jsem použil pro zkušební setřídění pole 35 mil. řádků v paměti.
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dist(0, 0x7FFFFFFF);
for (int i = 0; i < 10; ++i) {
cout << dist(gen) << " ";
}
#2 MilanL
Neleze z toho vůbec nic, překladač mi hlásí chybu, že musí být hodnoty rozsahu generovaných čísel float čísla. Na netu jsem našel "x" příkladů náhodného generátoru ale ani jeden pořádně nefunguje tak, jak bych potřeboval tj, generovat kladná DWORD čísla v rozsahu 0 až 0x7FFFFFFF.
...requires one of float, double, or long double.
#11 MilanL
Visual Studio 2017, které je zdarma, umí bez problémů zkompilovat externí x64 ASM funkci volanou z C++. Sám to tak používám. Jak na to je popsáno zde https://deviorel.wordpress.com/2015/01/19/compiling-64-bit-assembler-code-in-visual-studio-2014/
Potřebuji předat funkci VirtualAlloc požadovanou velikost paměti, kterou vypočítám pomocí proměnné. Parametr je ale typu SIZE_T dwSize
Toto nefunguje,
static const SIZE_T size_L = n1 *125;
BYTE* L_adr = static_cast<BYTE*>(VirtualAlloc(NULL, size_L, MEM_COMMIT, PAGE_READWRITE));
size_L je bez ohledu na hodnotu int n1 vždy 125.
Pokud potřebuji alkovat pamět s konkrétní hodnotou tak to funguje
static const SIZE_T giga = 1024 * 1024 * 1024;
static const SIZE_T size = 8 * giga;
BYTE* ptr = static_cast<BYTE*>(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
Jak do size_L dostat vypočítanou velikost potřebné velikosit paměti ?
Už to funguje :-)
Funkce na převod
Int Prevod(__int64 ASCII_adresa, int ASCII_delka, int ASCI_pozice)
{
*(BYTE *)(ASCII_adresa + ASCI_pozice + ASCII_delka) = 0x00;
return atoi(reinterpret_cast<CHAR*>(ASCII_adresa + ASCI_pozice));
}
Cyklus pro úpravu 50 mil. řádků:
for (int i = 0; i < radku; i++) //Cyklus pro úpravu dat
{
misto = adresa + (i * 125); //Načteme ID
x = Prevod(misto, 8, 0);
*(DWORD *)(misto + 56) = x; //a uložíme na pozici 56
}
#2 hlucheucho
Díky, tu nulu na konec mohu doplnit. Funkce by pak mohla vypadat takto:
int Prevod(int pocet, __int64 misto)
{
*(BYTE *)(misto + pocet) = 0x00;
return stoi(*(CHAR*)((misto));
}
Visual Studio mi ale červeně podtrhlo "stoi" a ";" na konci řádku. Co je špatně ?
Potřeboval bych poradit, jak převést ASCI čísla, kterámám uloženo v paměti, nejsou ukončeno \0 !!! např. " 80766". Znám jeho délku a pozici prvního znaku v paměti. Jde mi funkci, kterou pak budu volat v cyklu.
int ASCI_na_cislo(int ASCIdelka, int ASCIpozice)
{
return stoi(reinterpret_cast<string*>(adresa));
}
adresa je 64bit adresa na začátek paměti ke které je potřeba přičíst pozici prvního znaku (ASCIpozice).
Příklad volání funkce z Main:
x = ASCI_na_cislo(8, 0)
Případně provést koverzi pomocí stringstream class nebo sscanf() ?
Tak už mi vykreslování pomocí Polyline chodí :-). Zádrhel byl v tom, že jsem chybně přepočítával souřadnice bodů na body na obrazovce a ještě jsem měl uloženo nejdříve Y a pak X ... Odkaz na body v paměti
reinterpret_cast<POINT*>(memory)
funguje v pohodě.
Body pak nenavazovaly na sebe a funkce Polyline to nemohla vykreslit. Díky všem za rady ;-).
#57 MilanL
Reálně potřebuji vyřešit ale tohle:
// Test.cpp : Zkouška přiřazení dvojic hodnot v paměti do třídy POINT
//
#include "stdafx.h"
#include <stdlib.h>
int main()
{
void *memory = calloc(12, sizeof(int)); //Alokujeme pole pro 6 INT párů po 4 bytech
int *ptr = (int *)memory;
for (int i = 0; i < 12; i++)
{
*ptr = 7; // Nevím jak tam zadata, aby se ukládala proměnná "i"
printf("%i\n", *ptr);
ptr++; // Posun na začátek dalšího DWORD
}
// Tady by pak mělo být přiřazení uložených hodnot v paměti do třídy POINT (asi včetně počtu dvoji bodů tj. 6)
free(memory);
return 0;
}
#50 MilanL
Pánové, musí se na to úplně jinak. Dostal jsem radu:
As input, Polyline() takes a pointer to an array of POINTstructs, and the number of elements in the array.
POINT has two data members that are both of type LONG, so if you have an existing array of DWORD pairs in memory, you could simply type-cast that address to a POINT* pointer when you pass it to Polyline() (as DWORD and LONG have the same byte size in the Win32 API), eg:
DWORD *pairs = ...;
DWORD numPairs = ...;
...
Polyline(hdc, reinterpret_cast<POINT*>(pairs), numPairs);
However, a safer approach is to simply allocate a separate POINT[] array in memory and copy the DWORD values into it, then pass that array to Polyline(), eg:
DWORD *pairs = ...;
DWORD numPairs = ...;
...
POINT *points = new POINT[numPairs];
for(DWORD i = 0; i < numPairs; ++i)
{
points[i].x = pairs[i*2];
points[i].y = pairs[(i*2)+1];
}
Polyline(hdc,
FYI, in your question you mention GDI+, but Polyline() is part of GDI, not GDI+. The GDI+ equivilent is Graphics::DrawLines(), but it requires an array of Pointclass objects instead of POINT structs. You can't safely type-cast a DWORD array to Point*, you would have to actually construct the individual Point objects (using the Point(int,int) constructor), similar to above, eg:
DWORD *pairs = ...;
DWORD numPairs = ...;
...
Point *points = new Point[numPairs];
for(DWORD i = 0; i < numPairs; ++i)
points[i] = Point(static_cast<INT>(pairs[i*2]), static_cast<INT>(pairs[(i*2)+1]));
Graphics *g = Graphics::FromHDC(hdc);
Pen pen(...);
g->DrawLines(&pen, points, numPairs);
delete g;
delete[] points;
Pomocí reinterpret_cast mi příkaz Polyline už začal něco kreslit, zatím blbě, musím zkontrolovat přepočet na správné pozice.
#37 MilanL
Stále bohužel nefunguje správné přiřazení bodů v paměti do apt.
POINT apt[156];
takto to funguje správně. Tj. když v breaku najedu na apt, zobrazí se okno s adresou apt a následně 156 párů bodů x, y
Pokud ale použiju kód
bodu = *(DWORD *)(bsrc + 0x01719F0F6B + 4 * x + 4);
POINT *apt = (POINT*)(bsrc + 0x01719F0F6B + 8 * x + 8)[bodu];
for (int i = 0; i < bodu; i++) // Naplníme pole pro vynášení bójí
{
if (apt[i].x > 180000)
{
apt[i].x = 960 - ((-1)*apt[i].x - 180000) / (float)180000 * 960;
}
else {
apt[i].x = (float)apt[i].x / (float)180000 * 960 + 960;
}
if (apt[i].y > 90000)
{
apt[i].y = 540 - ((-1)*apt[i].y - 90000) / (float)90000 * 540;
}
else {
apt[i].y = (float)apt[i].y / (float)90000 * 540 + 540;
}
}
POINT je špatně nastaven a data se zapisují mimo správnou paměť
I když z řádku vyhodím [body]. tj. počet bodů, nepřiřadí se 2 315 bodů správně a Polyline nic nevykreslí
#30 MilanL
tam je něco v paměti na těch prvních 4 BYTEch?
Ano, to X je počet nalezených bóji DWORD, které se pohybovaly mezi dvěma zadanými oblastmi (ve tvaru čtverce). Dosud jsem postupoval tak, že mi program našel počet bójí a čísla bóji. Ta jsem pak zadal do dotazu PowerQuery v Excelu, ke kterému jsem měl externě připojený ten velký soubor. Výsledkem byly souřadnici bodů dané bóje v Excelu. Excelový soubor se souřadnicemi jsem pak pomocí https://www.earthpoint.us/ExcelToKml.aspx převedl na KML soubor a vynesl na Google Earth. V neplacené verzi je tam ale omezení jen na 200 bodů, počet bodů musím proti poměrně snížit. Bóje ale mohou obsahovat klidně 5 000 bodů. Výsledekm je pak např. takováto mapa.
#32 KIIV
Nejsem žádný programátor, to jsem se v C++ potřeboval, jsem se z příkladů naučil za měsíc. Pokud by bylo možné vynést křivky rovnou z ASM udělal bych to (zavolat z ASM funkci Polyline v C++). Oproti C++ nemám s assemblerem žádný problém. Zkus v C++ hledat v 50 milionech řádcích ;-). Mapování souboru mi nepomůže, pokud načtu celý soubor do paměti, rychleji s ním pracovat nelze.
#26 MilanL
Dal jsem tam:
apt[0].x = -10127;
apt[0].y = 73025;
to funguje. Nehlásí to žádnou chybu, data se správně uloží a apt odkazuje na správnou adresu paměti tj. na ty první dvě hodnoty. Viz screen shot obrazovky. Na adrese 0x000002360c3c0fb3 jsou správně uloženy obě hodnoty (DWORD) x= -10127 tj. 71 D8 FF FF a y=73025 tj. 41 1D 01 00. Teď ještě do apt nějak dostat počet bodů.
#24 MilanL
nj, ale tam žádná data načtená nejsou, tak ti to nemůže nic vracet žádný počet vbojí, žádná ID nebo počty bodů a už vůbec ne data bodů
Data tam samozřejmě jsou, ukládá mi je tam ASM funkce a při breaku C++, výpis RAM paměti, je tam spolehlivě vidím. Díky za ukázku v C++ která ale nevystihuje podstatu věci tj. přístup na data ze skutečné RAM paměti. V programu by jsi musel použít VirtualAlloc, do paměti si zapsat nějaké hodnoty a pak ty hodnoty použít v POINT class.
#18 gna
Nějak se motáme v kruhu. Myslím, že jsem zcela jasně popsal, o co mi jde. Strukturu POINT potřebuji nastavit na má data v paměti a to včetně jejich počtu. Nejde jen úpravu souřadnic pro jejich vynesení do Full HD okna (1980 x 1080 bodů). Správné nastavení na data v paměti potřebuji pro jejich vykreslení pomocí funkce Polyline, která použivá parametr apt. Když na něj při ladění programu najedu, ukazuje počet bodů 156...
#16 MilanL
Ve výpočtech odkazů není chyba, zkontroloval jsem si to. Problém je, že nefungují odkazy na POINT do paměti podle pokynů výše:
INT32 LAT[156]{ -10127, -10291, -11002, -11149, -10807, -9789, -8948, -8328, -8183, -7918, -7259, -6590, -5993, -7324, -8584, -8876, -8603, -8262, -8858, -8326, -7710, -8189, -7419, -6292, -5564, -5227, -4379, -3494, -3382, -3298, -4022, -4732, -3894, -4604, -6124, -6672, -6904, -7157, -7512, -7987, -8552, -9248, -10438, -10727, -11218, -11566, -12788, -12717, -12070, -11746, -11839, -11238, -11477, -12224, -12864, -14048, -14053, -13786, -14131, -14516, -14395, -14562, -14536, -14487, -14604, -14514, -14833, -14992, -15294, -15153, -15899, -16565, -17287, -17540, -18308, -18508, -18127, -18594, -19131, -19656, -21120, -21738, -21998, -20052, -19360, -19651, -22041, -26186, -25980, -24102, -23168, -22478, -22066, -22263, -23992, -24398, -24821, -26567, -25563, -26156, -25605, -26105, -26391, -25959, -25354, -25366, -26465, -26772, -25812, -25405, -25293, -26805, -29343, -31190, -31647, -32224, -32780, -32636, -32124, -32648, -33977, -34820, -36280, -36874, -35570, -35237, -33215, -34272, -33742, -32777, -32337, -31360, -31185, -31081, -30244, -28997, -27578, -27596, -27393, -27207, -27258, -27371, -26831, -26142, -26505, -26753, -26752, -26340, -26319, -26206, -26212, -26476, -26642, -26790, -26789, -26490
};
INT32 LON[156]{ 73025, 73056, 72348, 71368, 70694, 70816, 69896, 69756, 68782, 67560, 66618, 66209, 66586, 66171, 65126, 63698, 62961, 62424, 62597, 63580, 64129, 64918, 66398, 67329, 67455, 68054, 70343, 72531, 74184, 76406, 78643, 80838, 83212, 84528, 86157, 87738, 88750, 89554, 90109, 90485, 90798, 91481, 90374, 88523, 86799, 84249, 83107, 81232, 80334, 78805, 77591, 76457, 75045, 73544, 72271, 71062, 69696, 68603, 67876, 67306, 66004, 64291, 62692, 61926, 61540, 61192, 61142, 61042, 61153, 61206, 60941, 60356, 59374, 58525, 57722, 57662, 56746, 55771, 55351, 54571, 54200, 54324, 53027, 51690, 50442, 49689, 48362, 46033, 41235, 41275, 41375, 40487, 39458, 38626, 39822, 40245, 40429, 40149, 39217, 38947, 39100, 36916, 38485, 36234, 38713, 40824, 41513, 41779, 41089, 40006, 38967, 38710, 36581, 36241, 35660, 34026, 34544, 32490, 31168, 30185, 29004, 26684, 23031, 15876, 15791, 15628, 13732, 12223, 11979, 12393, 12141, 11593, 10385, 8649, 8551, 9156, 7629, 6108, 6080, 5060, 4762, 4922, 4524, 3795, 3522, 3814, 3792, 2947, 2949, 2763, 2349, 2648, 2273, 1383, 775, 245
};
//POINT apt[156]{};
POINT *apt = (POINT*)(bsrc + 0x01719F0F6B + 8 * x + 8)[*(DWORD *)(bsrc + 0x01719F0F6B + 4 * x + 4)];
for (int i = 0; i < 156; i++) // Naplníme pole pro vynášení bójí
{
apt[i].x = (float)LON[i] / (float)180000 * 960 + 960;
apt[i].y = (float)abs(LAT[i]) / (float)90000 * 540 + 540;
}
Těch 156 hodnot mám v C++ jen pro účely testování. Pokud program při ladění zastavím za blokem řádků výše a najedu kurozorem na řádek s POINT na apt (address of points structure) zobrazí se mi:
apt|0x0000000000000000 <NULL>
Pokud odzávorkuji řádek //POINT apt[156]{}; a z řádku níže udělám komentář je vše v pořádku:
apt|0x00000093a04fe960 {{x=1349 y=600}, {x=1349 y=601}, {x=1345 y=606}, {x=1340 y=606}, {x=1337 y=604}, ...}
#11 Kevil
Upravil jsem na reálný kód:
POINT *apt = (POINT*)(bsrc + 0x01719F0F6B + 8 * x + 8)[*(DWORD *)(bsrc + 0x01719F0F6B + 4 * x + 4)];
kde údaje v závorkách ukazají na správné místo paměti, první je odkaz na souřadnice bodů a druhý odkaz na počet bodů = 2 315. Překlad proběhl bez závad, ale ve struktuře je místo počtu bodů 0, páry bodů proto nejsou vidět.
Pro vysvětlení to x = 8 udává počet nalezených bojí, jejichž trasy chci pak pomocí Polyline vykreslit. Než se to podaří rozchodit, tak nyní pracuji pouze s daty první bóje. Data mám v paměti uložena ve tvaru DWORD od bsrc + x01719F0F6B + 4: počet bójí (8), ID bójí (8x), počet bodů pro bóji (ID=1, ID=2,...) a pak vlastní souřadnice bodů, nejdříve x1, y1, x2, y2... pro bóji ID=1 atd.
#7 KIIV
VirtualAlloc volám z C++ a adresu pak předám při volání ASM funkci (např. Funkce_Uprav). Alokuji 7 GB do kterých načtu 6 GB externí soubor s daty, který obsahuje 50 mil. řádků. Soubor musím načíst na 3x, nepodařilo se mi přijít na to, jak ho načíst najednou, to ale není žádný problém. načtení trvá cca 3 sekundy. Na notebooku mám 24 GB RAM. Část funkčního kódu pro alokaci RAM a načtení souboru:
_int64 FileSize(const wchar_t* name)
{
WIN32_FILE_ATTRIBUTE_DATA fad;
if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
return -1; // error condition, could call GetLastError to find out more
LARGE_INTEGER size;
size.HighPart = fad.nFileSizeHigh;
size.LowPart = fad.nFileSizeLow;
return size.QuadPart;
}
VOID OnPaint(HDC hdc)
{
delka = FileSize(fname); // 64 bitů
zbyva_nacist = delka;
printf("%lli\n\n", FileSize(fname));
//* Zkusíme otevřít soubor pro čtení *//
HANDLE handle = CreateFile(fname, GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
//if (handle == INVALID_HANDLE_VALUE)
// report_error("Unable to open input file!\n");
//* Alokujeme pamět pro celý soubor *//
static const SIZE_T giga = 1024 * 1024 * 1024;
static const SIZE_T size = 7 * giga;
BYTE* ptr = static_cast<BYTE*>(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
/*if (ptr == nullptr) {
std::cout << "Chyba pri alokaci pameti\n";
return 1;
}*/
std::cout << "Pamet alokovana\n";
BYTE* bsrc = ptr;
//* Načteme soubor *//
DWORD bytes_read;
for (int i = 1; i <= 3; i++) {
if (i < 3) {
cti_znaku = cti_blok;
}
else
{
cti_znaku = delka - nacteno;
}
ReadFile(handle, ptr, cti_znaku, &bytes_read, nullptr);
nacteno += bytes_read;
ptr += bytes_read;
}
CloseHandle(handle);
// Upravíme načtená data v poli
adresa = (__int64)bsrc;
__int64 result = Funkce_Uprav(adresa);
#6 gna
Díky, to je skoro přesně to, co jsem potřeboval. Teď mi to již ukazuje správně na data v paměti, ale chybí tam ještě, jak zadat počet bodů.
Původně jsem tam měl natvrdo:
POINT apt[156];
teď mi sice apt odkazuje správně na data v paměti, použit reálný kód:
POINT *apt = (POINT*)(bsrc + 0x01719F0F6B + 8 * x + 8);
ale struktura POINT neví, kolik bodů tam je. Potřebuji ještě předat odkaz na DWORD v paměti s počtem bodů.
#3 gna
Ty složené závorky tam asi být nemusí, ale překladač s tím nemá problém.
Jak pracovat se strukturou buodů vím, o to mi nejde. Jak jsem psal z C++ volám vlastní funkci v x64 assembleru, která má data (x, y) připraví v paměti RAM. Pamět RAM si pro to alokuji pomocí funkce VirtualAlloc. Při vynášení bodů pomocí funkce
Polyline(hdc, apt, 156);
potřebuji v proměnné "apt", nastavit odkaz na místo v paměti RAM, kde mám data uložena. Jde tedy o to nějak "vnutit" proměnné apt adresu RAM paměti, kterou mám k dispozici.
v C++ potřebuji řádek
POINT apt[156]{}
nahradit odkazem na strukturu bodů vektoru, který mám uložen v paměti (z C++ volám vlastní funkci v assembleru) něčím jako:
POINT má_adresa_na_pole_bodů[*(DWORD *)(pocet)]
kde je "počet" pointer na adresu paměti s počtem bodů a "má_adresa_na_pole_bodů" je DWORDLONG pointer (64 bit) na začátek struktury bodů v paměti.
Jak na to ?
Díky, podívám se na to.
Potřebuji načíst najednou velký textový soubor 6,32 GB a zkopírovat z něj některé hodnoty v řádcích do pole o velikosti 50 mil. řádků s pevnou délkou 10 bytů (tj. 0,5 GB). S polem pak bude dále pracovat. V NB mám pamět 24 GB tak by s tím neměl být problém. V C++ jsem ale naprostý začátečník, uvítám např. odkaz, jak na to.